我正在学习Haskell,我编写了这段代码来测试Haskell的一些概念。
identifyThing :: [arg] -> String
identifyThing arg = "This looks like a " ++
case arg of
[] -> "empty list"
[arg] -> "list"
arg -> "something else"
main :: IO ()
main = putStrLn (identifyThing [])
putStrLn (identifyThing [1..10])
putStrLn (identifyThing ())
putStrLn (identifyThing 1)
我在主声明的第一行收到错误:不能将7个参数应用于putStrLn。我想这是因为我不知道如何告诉haskell我没有把论据包装到下一行。
如果有人能告诉我我做错了什么,我将不胜感激。感谢。
答案 0 :(得分:7)
更长的答案是,在Haskell中,你不能将线条组合在一起并期望它们按顺序工作。当您编写do
时,它不是{} - 样式块或其他内容的语法,它是使用>>=
函数将行连接到更大行的语法。所以当你写do
时,它实际上只是一行:
main = putStrLn (identifyThing []) >>= \_ -> putStrLn (identifyThing [1..10]) >>= \_ -> putStrLn (identifyThing [1])
模式匹配(如case
或使用多个方程的等效定义)从上到下工作。
Haskell的整个想法是你不能写垂直程序 - 你只能编写水平程序:)通常你可以将你的“垂直”程序重新编写成一个较短的“水平”程序。 E.g。
main = mapM_ (putStrLn . identifying) [[], [1..10], [1]]
是另一种说“水平”想要“垂直”说出来的方式。
对于初学者do
,<-
和return
结构具有误导性。因此,您应该使用>>=
,>>
,\ ->
和return
,然后了解如何使用<$>
,<*>
,{{1 } {},.
以及liftM2
和Control.Monad
中的其他函数。此外,在许多情况下,您可以重新设计算法,因此不再需要“垂直”代码。
对于您的示例,一个易于理解的初学者代码将是:
Control.Applicative
答案 1 :(得分:4)
修正了它,在main之后使用“do”,加上换行符,就可以了。
这是我过去的工作(也纠正了程序的其他部分):
identifyThing :: [a] -> String
identifyThing arg = "This looks like " ++
case arg of
[] -> "an empty list"
[x] -> "a list with one element"
x -> "a list with more than one element"
main :: IO ()
main = do
putStrLn (identifyThing [])
putStrLn (identifyThing [1..10])
putStrLn (identifyThing [()])
putStrLn (identifyThing [1])