2016-07-07 60 views
1

一个 “做” 语法中我知道这个工程:HASKELL ---用 “让” 在GHCI

do name <- getLine; let nameTag = "Hello, my name is " ++ name in putStrLn nameTag 

除了这段代码在加载到GHCI:

hey = do 
    name <- getLine 
    let nameTag = "Hello, my name is " ++ name 
    putStrLn nameTag 

但是,这并不工作:

do name <- getLine; let nameTag = "Hello, my name is " ++ name; putStrLn nameTag 

给出以下错误消息:

<interactive>:142:82: 
    parse error (possibly incorrect indentation or mismatched brackets) 

它为什么不起作用?我可以使它工作吗?如果是,那么如何?

+1

请格式化您的代码。 –

+1

问题是解析器认为你的代码的结构是'let {nameTag = ...; putStrLn nameTag“'它在哪里期望赋值而不是'putStrLn nameTag'。 – Bakuriu

回答

5

是的,你可以使用大括号围绕让利结合(S)的歧义解析:

do name <- getLine; let { nameTag = "Hello, my name is " ++ name }; putStrLn nameTag 
+0

谢谢!我试图用括号,但没有成功。 Haskell中大括号和括号之间的根本区别是什么? –

+1

@RafałPłaszczyk括号用于分隔子表达式。大括号是用于消除语言语法的歧义。 (哦,并记录语法......) – MathematicalOrchid

+1

@RafałPłaszczyk你可能注意到Haskell是缩进敏感的。基本上,括号允许将所有内容写入一行,将块('do,let,where,case')写入与'{entry1; entry2; ...}'相同的缩进级别。通常不需要,除了GHCi。在很多情况下,只有';'就足够了,括号可以省略。 – chi

4

,以补充麦肯纳答案,错误可以解释如下:比较这两个线

do name <- getLine; let name1 = "One"; putStrLn name1 
do name <- getLine; let name1 = "One"; name2 = "Two"; putStrLn name1 

人类读者可以看到,实际上他们的意思

do { name <- getLine; let { name1 = "One" } ; putStrLn name1 } 
do { name <- getLine; let { name1 = "One"; name2 = "Two" }; putStrLn name1 } 

但是解析器不那聪明。 当Haskell的解析器看到的共同代码部分

do name <- getLine; let name1 = "One"; 
            --^-- 

它必须决定最后;是否属于do水平(如在上述第一种情况),或到let水平(第二种情况)。事实证明,它选择了let,并在以后失败。