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

Chr*_*her 9 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)
Run Code Online (Sandbox Code Playgroud)

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

tutorial03.hs:9:13:
Illegal signature in pattern: [Person] people
    Use -XScopedTypeVariables to permit it
Run Code Online (Sandbox Code Playgroud)

使用XScopedTypeVariables标志我得到

tutorial03.hs:10:17: Not in scope: type variable `people'
Run Code Online (Sandbox Code Playgroud)

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

pig*_*ker 25

Luqui说缩进就是问题.编译器将您的定义视为一样

let people :: [Person] people = read people_text
Run Code Online (Sandbox Code Playgroud)

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

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

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

let people :: [Person]
    people = read people_text
Run Code Online (Sandbox Code Playgroud)

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

let people :: [Person] ;
        people = read people_text
Run Code Online (Sandbox Code Playgroud)

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

let people = read people_text :: [Person]
Run Code Online (Sandbox Code Playgroud)

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