哈斯克尔“在哪里”缩进:为什么必须缩进标识符之后?
此代码:
import Data.Char (digitToInt)
myInt :: String -> Int
myInt [] = error "bad input: empty string"
myInt (x:xs)
| x == '-' = -1 * myInt xs
| otherwise = foldl convert 0 (x:xs)
where convert acc x
| x `elem` ['0'..'9'] = 10 * acc + digitToInt x
| otherwise = error ("bad input: not an int - " ++ [x])
失败:
前奏> :l safeListFs.hs
[1 of 1] 编译 Main( safeListFs.hs,解释)safeListFs.hs:9:8:解析错误(可能缩进不正确)
失败,已加载模块:无。
但这个版本:
import Data.Char (digitToInt)
myInt :: String -> Int
myInt [] = error "bad input: empty string"
myInt (x:xs)
| x == '-' = -1 * myInt xs
| otherwise = foldl convert 0 (x:xs)
where convert acc x
| x `elem` ['0'..'9'] = 10 * acc + digitToInt x
| otherwise = error ("bad input: not an int - " ++ [x])
还可以:
前奏> :l safeListFs.hs
[1 of 1] 编译 Main( safeListFs.hs,解释)
好的,模块已加载:Main。
我不明白为什么最后两个缩进很重要。
This code:
import Data.Char (digitToInt)
myInt :: String -> Int
myInt [] = error "bad input: empty string"
myInt (x:xs)
| x == '-' = -1 * myInt xs
| otherwise = foldl convert 0 (x:xs)
where convert acc x
| x `elem` ['0'..'9'] = 10 * acc + digitToInt x
| otherwise = error ("bad input: not an int - " ++ [x])
Fails:
Prelude> :l safeListFs.hs
[1 of 1] Compiling Main ( safeListFs.hs, interpreted )safeListFs.hs:9:8: parse error (possibly incorrect indentation)
Failed, modules loaded: none.
But this version:
import Data.Char (digitToInt)
myInt :: String -> Int
myInt [] = error "bad input: empty string"
myInt (x:xs)
| x == '-' = -1 * myInt xs
| otherwise = foldl convert 0 (x:xs)
where convert acc x
| x `elem` ['0'..'9'] = 10 * acc + digitToInt x
| otherwise = error ("bad input: not an int - " ++ [x])
is ok:
Prelude> :l safeListFs.hs
[1 of 1] Compiling Main ( safeListFs.hs, interpreted )
Ok, modules loaded: Main.
I can't figure out why those two last indents matter.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
基本上,Haskell 会记录
where
之后第一个非空格字符出现的列(在本例中为convert
的c
),并处理以下内容从该列开始的行作为where
内的新定义。延续上一行定义的行(例如
|
防护)必须缩进到第一个非空格字符的右侧(c< /code> 在你的代码中)。
c
左侧缩进的行将位于where
之外(例如,下一个顶级函数的开头)。where
之后的第一个字符的列至关重要,即使它位于新行上:Basically, Haskell notes the column where the first non-space character after
where
appears (in this case, thec
ofconvert
) and treats following lines beginning in that column as new definitions inside thewhere
.A line that continues the definition of the previous line (such as your
|
guards) must be indented to the right of the first non-space character (c
in your code).A line indented to the left of
c
would be outside thewhere
(for example, the start of your next top-level function).It's the column of the first character following
where
that is crucial, even if it's on a new line:来自 http://www.haskell.org/onlinereport/syntax-iso.html。
这也会失败:
呃,我不擅长解释事情。在
where
关键字之后有一个新的上下文,因为您可以在其中指定多个函数 - 请记住您的程序以隐式module Main where
开头,所以我认为这是合乎逻辑的要求函数体缩进,就像在模块级别一样(编译器期望 M 和 N 列上有另一个标识符,并且声明体进一步缩进)。From http://www.haskell.org/onlinereport/syntax-iso.html.
This would also fail:
Uh, I'm bad at explaining things. There's a new context after
where
keyword, because you can specify more than one function in there -- remember that your program begins with implicitmodule Main where
, so I think it's logical to require function body to be indented, just like on the module level (compiler expects another identifier on columns M and N, and declaration bodies to be further indented).因为您应该始终缩进函数定义。
(在您的情况下,所有在
where
中同一列开始的内容都被视为“同一级别”定义)。Because you should always indent function definitions.
(In your case, all things started at same column in
where
are considered "same-level" definition).