I've decided to teach myself Haskell and I have never been so frustrated in all my life. I am going through the tutorial at http://lisperati.com/haskell/ which is the easiest one I could find. All that I am trying to do is read a text file called people.txt which contains a list of numbers and print the length of the list. This code is straight from the tutorial.
import Data.List
type Person = [Int]
main = do
people_text <- readFile "people.txt"
let people :: [Person]
people = read people_text
putStr "Number of people "
putStr (length people_text)
When I try to run the file with runHaskell tutorial03.hs I get this error message
tutorial03.hs:9:13:
Illegal signature in pattern: [Person] people
Use -XScopedTypeVariables to permit it
Using the XScopedTypeVariables flag I get
tutorial03.hs:10:17: Not in scope: type variable `people'
Could someone please explain what I am doing wrong.
Luqui's right that indentation is the issue. The compiler is treating your definition as if it were
let people :: [Person] people = read people_text
which does indeed look like you're writing a type signature in a pattern (and using people
both as the function name and a pattern variable, to boot -- peculiar but permitted!).
Crucially, let
is a layout keyword, introducing a block of lines which should all be indented to the same horizontal position. By following the signature with a more-indented line, you indicate that you're contuing the line with the signature, rather than starting a new line for the actual definition. If you don't like this fussy layout convention, you can use noisy semicolons.
If you want your definition to be treated as two lines, you either need to be careful to line up the people
s vertically...
let people :: [Person]
people = read people_text
or to signal the line ending explicitly with a semicolon.
let people :: [Person] ;
people = read people_text
The former would be preferable, although I expect most Haskellers would just supply a type annotation for read people_text
rather than a signature for the definition, like this:
let people = read people_text :: [Person]
Once you've fixed that, you'll need to contend with the fact that the length of the list is a number, but putStr outputs strings. The print
command may be more useful for this purpose.
change it to this, works for me:
...
let people :: [Person]
people = read people_text
...
print (length people_text)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With