2

我正在学习 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 我没有将论点包装到下一行。

如果有人能告诉我我做错了什么,我将不胜感激。谢谢。

4

2 回答 2

7

一个更长的答案是,在 Haskell 中,您不能将行放在一起并期望它们按顺序工作。当您编写do它时,它不是 { } - 样式块或其他东西的语法,而是使用>>=函数将行连接成更大行的语法。因此,当您编写时do,实际上它只是一行:

main = putStrLn (identifyThing []) >>= \_ -> putStrLn (identifyThing [1..10]) >>= \_  -> putStrLn (identifyThing [1])

模式匹配(如case使用多个方程或等效定义)从上到下工作。

Haskell 的整个想法是你不能编写垂直程序 - 你只能编写水平程序 :) 通常你可以将你的“垂直”程序重新编写成一个更短的“水平”程序。例如

main = mapM_ (putStrLn . identifying) [[], [1..10], [1]]

是另一种表达“水平”你想说“垂直”的方式。

对于初学者来说do<-构造return是相当具有误导性的。所以你应该使用>>=, >>,\ ->然后return学习如何使用<$>, <*>, .,和和liftM2的其他函数来缩短它。此外,在许多情况下,您可以重新设计算法,因此首先不再需要“垂直”代码。Control.MonadControl.Applicative

对于您的示例,一个易于理解的初学者代码将是:

main = putStrLn (identifyThing [1..10]) >> putStrLn (identifyThing ()) >> putStrLn (identifyThing 1)
于 2012-10-01T11:47:42.267 回答
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])
于 2012-10-01T07:58:19.500 回答