我尝试学习 Haskell,并努力将 do 语法转换为 monad。 所以,我把它归结为一个小例子。
我得到了这个:
work :: String
work = do
let arr = ["Get", "this", "to", "work"]
let s = unlines arr
s
main :: IO ()
main = putStrLn work
我将其改写为:
work :: String
work = ["Get", "this", "to", "work"] >>= unlines >>= return
main :: IO ()
main = putStrLn work
这给了我:
monad-do.hs:2:42: error:
• Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [Char] -> [Char]
Actual type: [String] -> String
• In the second argument of ‘(>>=)’, namely ‘unlines’
In the first argument of ‘(>>=)’, namely
‘["Get", "this", "to", "work"] >>= unlines’
In the expression:
["Get", "this", "to", "work"] >>= unlines >>= return
|
2 | work = ["Get", "this", "to", "work"] >>= unlines >>= return
| ^^^^^^^
弄清楚错误消息试图告诉我什么后,我开始工作了:
work :: String
work = ["Get", "this", "to", "work"] >>= (\arr -> unlines [arr]) >>= return
main :: IO ()
main = putStrLn work
问题: 为什么我需要将
[arr]
而不是 arr
传递给 unlines
?
总体来说:
do
foo <- bar
...
在没有
do
符号的情况下翻译为 bar >>= \ foo -> ...
和
do
let foo = bar
...
翻译为
let foo = bar in ...
。 这些不相同:只有 <-
转换为 >>=
。
你在翻译中忽略了这一点。