reverse2lines
如何转换为使用>>=
语法?就像addOneInt
转换为addOneInt'
?
addOneInt :: IO ()
addOneInt = do line <- getLine
putStrLn (show (1 + read line :: Int))
addOneInt' :: IO ()
addOneInt' = getLine >>= \line ->
putStrLn (show ( 1 + read line :: Int))
reverse2lines :: IO ()
reverse2lines =
do line1 <- getLine
line2 <- getLine
putStrLn (reverse line2)
putStrLn (reverse line1)
另请考虑阅读后续问题question及其有价值的答案。
答案 0 :(得分:5)
您可以从您已经知道的内容中安全地推断出它。首先完全括号化addOneInt'
:
addOneInt' = getLine >>= (\line ->
putStrLn (show (1 + read line :: Int)) )
接下来,您reverse2lines
可以等效地写为
reverse2lines =
do { line1 <- getLine ;
do { line2 <- getLine ;
do { putStrLn (reverse line2) ;
do { putStrLn (reverse line1) } } } }
根据需要应用已经用于addOneInt
的一步转换,您将获得
reverse2lines' :: IO ()
reverse2lines' =
getLine >>= (\line1 ->
getLine >>= (\line2 ->
putStrLn (reverse line2) >>
putStrLn (reverse line1) ) )
从语法上讲,lambda表达式的括号可以省略,但是在这里明确地写它们有助于澄清并明确这些函数的嵌套结构,特别是如果我们排列缩进。
完整翻译安排monad的fail
函数在模式不匹配时被调用,但由于变量模式(line1
,line2
)是无可辩驳的,因此这个翻译是事实上确切。
答案 1 :(得分:4)
类型x <- m
的语句可以翻译为m >>= \x -> ...
,而返回值不像m
那样绑定的语句可以翻译为m >> ...
reverse2lines :: IO ()
reverse2lines = getLine
>>= \line1 -> getLine
>>= \line2 -> putStrLn (reverse line2)
>> putStrLn (reverse line1)
翻译不准确 - fail
monad函数使事情变得复杂。您可以阅读here,但据我所知,在处理IO
monad时无关紧要。
答案 2 :(得分:1)
以下是Will仅使用>>=
:
reverse2lines' :: IO ()
reverse2lines' =
getLine >>= (\line1 ->
getLine >>= (\line2 ->
putStrLn (reverse line2) >>= (\_ ->
putStrLn (reverse line1) )))
获得的经验教训:do
中的排序只对应于lambda表达式的嵌套。