Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple Haskell program causes 'Illegal signature in pattern' error

Tags:

haskell

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.

like image 660
Christopher Avatar asked Jul 22 '11 08:07

Christopher


2 Answers

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 peoples 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.

like image 55
pigworker Avatar answered Nov 13 '22 04:11

pigworker


change it to this, works for me:

...
    let people :: [Person]
        people = read people_text

...
    print (length people_text)
like image 25
yihuang Avatar answered Nov 13 '22 06:11

yihuang