我担心我会理解这一点和let
一般情况。
以下代码:
splitWith tf xs
|(null xs) = [[]]
|((length xs) == 1) = [xs]
|otherwise = let tpl = (break tf xs)
x = (fst tpl)
xrst = (snd tpl)
in [[x] ,(splitWith tf (tail xrst))]
创建此语法错误:
[1/1]编译Main(ch04_exercise.hs,解释)
时的错误
ch04_exercise.hs:31:26:解析输入'x'
这是在我删除了Sublime Text 2中的标签并将空格放入以排列变量之后发生的。在我这样做之前,我在x
之后的=符号处得到了语法错误。
知道我做错了什么吗?
答案 0 :(得分:4)
in
必须与let
对齐或位于同一行:
| otherwise = let (x, xrst) = break tf xs
in [[x], splitWith tf (tail xrst)]
这就是为什么我通常更喜欢将let
放在自己的行上:
| otherwise =
let (x, xrst) = break tf xs
in [[x], splitWith tf (tail xrst)]
你也有不必要的括号,可以从一些模式匹配中受益(如上所示)。
答案 1 :(得分:2)
编译器抱怨x = (fst tpl)
因为它的左边缘没有与tpl =
对齐。
你只删除了一些标签。我将标签设为<------>
,空格设为.
:
splitWith tf xs
<------><------>|(null xs) = [[]]
<------><------>|((length xs) == 1) = [xs]
<------><------>|otherwise = let tpl = (break tf xs)
.........................x = (fst tpl)
.........................xrst = (snd tpl)
<------><------>.....in [[x] ,(splitWith tf (tail xrst))]
编译器使用8的倍数的tabstops。您认为tpl =
的位置与编译器认为的位置之间的差异为8表明编辑器的tabstops为4的倍数,如下所示:
splitWith tf xs
<--><-->|(null xs) = [[]]
<--><-->|((length xs) == 1) = [xs]
<--><-->|otherwise = let tpl = (break tf xs)
.........................x = (fst tpl)
.........................xrst = (snd tpl)
<--><-->.....in [[x] ,(splitWith tf (tail xrst))]
这看起来很好而且正确,但不是编译器看到它的方式!
如果你只使用没有任何标签的空格,你就不会遇到这个问题,因为你的编辑必须按照编译器的想法来展示它。
我的编辑器让我指定当我按Tab键时,它应该插入一个选项卡显示的空格数,所以我使用它,这对于一个4的tabstop是安全的。如果你的编辑器可以这样做,请使用那个选择。 (如果没有,请考虑在编程时获得一个更聪明的编辑器。)
我的编辑器也有自动缩进和outdent,其中下一行复制前一行的空白缩进 - 这避免了问题。如果您的编辑器支持它,请启用它,因为它可以节省您的工作量,并且您不太可能得到解析错误。 (当我按下退格键时,我的编辑器会删除回到上一级别的缩进,这很不错。)
几乎所有编辑都可以更改显示标签的方式。如果你不能使用空格作为标签,你应该将tabstop改为8,因为它与ghc相匹配,并且你不太可能得到这个错误,但你仍然是最好使用空格。
答案 2 :(得分:0)
编译此代码(虽然类型错误)
我认为这里学到的一般教训是,如果你在下一行开始它们,排队let
分配会更容易。
splitWith tf xs
|(null xs) = [[]]
|((length xs) == 1) = [xs]
|otherwise = let
tpl = (break tf xs)
x = (fst tpl)
xrst = (snd tpl)
in [[x] ,(splitWith tf (tail xrst))]