为什么Haskell会将下一行代码识别为前一个函数的参数?
问题根源
你遇到的是Haskell do 表达式的语法规则问题:
如果你选择用显式大括号 {} 包裹do块的内容,必须用分号 ; 分隔每一条语句,否则Haskell不会通过换行/缩进识别语句边界,会把下一行的内容直接识别为上一行表达式的一部分。
你的代码中putStrLn ("test")和print ("works")之间没有分号,会被整体解析为putStrLn函数传入了三个参数:"test"、print、"works",和putStrLn :: String -> IO ()只接受一个字符串参数的类型完全不匹配,因此抛出对应的类型错误。
修复方案
有两种常用的修复方式:
方案1:保留显式大括号,补充分号分隔语句
main = do{ putStrLn ("test"); print ("works") }
方案2:使用Haskell更通用的缩进敏感语法,省略大括号和分号
保证do块内的所有语句左对齐,缩进层级一致即可,这也是绝大多数Haskell代码采用的风格:
main = do putStrLn "test" print "works"
注:上述代码中去掉了参数外层多余的括号,Haskell中函数应用优先级最高,putStrLn "test"和putStrLn ("test")语义完全等价。
内容的提问来源于stack exchange,提问作者jessisogray
相关产品推荐
相关产品推荐

