简单的Haskell程序导致“模式中的非法签名”错误

时间:2011-07-22 08:19:17

标签: haskell

我决定自学Haskell,我一生都没有这么沮丧。我正在阅读http://lisperati.com/haskell/的教程,这是我能找到的最简单的教程。我要做的就是读取一个名为people.txt的文本文件,其中包含一个数字列表并打印列表的长度。这段代码直接来自教程。

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)

当我尝试使用 runHaskell tutorial03.hs 运行该文件时出现此错误消息

tutorial03.hs:9:13:
Illegal signature in pattern: [Person] people
    Use -XScopedTypeVariables to permit it

使用XScopedTypeVariables标志我得到

tutorial03.hs:10:17: Not in scope: type variable `people'

有人可以解释一下我做错了什么。

2 个答案:

答案 0 :(得分:25)

Luqui说缩进就是问题的权利。编译器将您的定义视为

let people :: [Person] people = read people_text

确实看起来像是在模式中编写类型签名(并使用people作为函数名称和模式变量,以启动 - 特殊但允许!)。

至关重要的是,let布局关键字,引入了一系列线条,这些线条都应缩进到相同的水平位置。通过使用更多缩进的行跟踪签名,您指示您使用签名对该行进行约束,而不是为实际定义开始新行。如果您不喜欢这种繁琐的布局约定,则可以使用嘈杂的分号。

如果您希望将您的定义视为两行,则需要注意垂直排列people ...

let people :: [Person]
    people = read people_text

或以分号显示明确结束的行。

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

前者会更好,虽然我希望大多数Haskellers只提供read people_text的类型注释而不是定义的签名,如下所示:

let people = read people_text :: [Person]

一旦你解决了这个问题,你就需要应对列表长度为数字的事实,但putStr输出字符串。 print命令对此可能更有用。

答案 1 :(得分:1)

将其改为此,对我有用:

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

...
    print (length people_text)