恐怕我已经理解了这个和一般的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 of 1] 编译主 ( ch04_exercise.hs, 解释 )
ch04_exercise.hs:31:26:输入"x"上的解析错误
这发生在我摆脱了 Sublime Text 2 中的制表符并放入空格以排列变量之后。 在我这样做之前,我在x
后面的 = 符号处遇到了语法错误。
知道我做错了什么吗?
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)]
您还有不必要的括号,可以从一些模式匹配中受益(如上所述)。
抱怨x = (fst tpl)
,因为它的左边缘与tpl =
不对齐。
您只删除了部分选项卡。我将 tab 作为<------>
,将空格作为.
:
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 的倍数的制表位。您认为tpl =
的位置与编译器认为的位置之间的差异为 8,这表明编辑器的制表位为 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))]
这看起来不错且正确,但这不是编译器看到的方式!
如果您坚持使用空格,这是最简单的。更改编辑器的设置。
如果你只使用空格而没有任何制表符,你就不会遇到这个问题,因为你的编辑器必须按照编译器思考的方式显示它。
我的编辑器让我指定当我按制表符时,它应该插入制表符将显示为的空格数,所以我使用它,这对于制表位为 4 是安全的。如果您的编辑器可以执行此操作,请使用该选项。(如果没有,请考虑在编程时找一个更聪明的编辑器。
我的编辑器还具有自动缩进和缩进功能,下一行复制上一行的空格缩进 - 这避免了这个问题。如果您的编辑器支持它,请启用此功能,因为它可以节省您的精力,并且您不太可能收到解析错误。(当我按退格键时,我的编辑器会删除回以前的缩进级别,这很好。
几乎所有编辑器都可以更改选项卡的显示方式。如果你不能让它为制表符使用空格,你应该将制表符更改为 8,因为这与 ghc 匹配,而且你不太可能收到此错误,但你仍然最好使用空格。
了这段代码(尽管类型是错误的)
我认为这里学到的一般教训是,如果你在下一行开始排列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))]