我决定自学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'
有人可以解释一下我做错了什么。
答案 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)