在我在这里收到的建议下,我试图在没有外部绑定和返回的情况下重写功能,但是我似乎无法理解如何获得额外的io从中出来。
我有
good :: IO (Either Int String)
getit :: Either Int String -> Int
main :: IO ()
main = do
x <- fmap getit good
putStrLn $ show x
主工作正常。但是....
main2 :: IO ()
main2 = do
putStrLn $ show $ fmap getit good
-- let's try totally without do
main3 :: IO ()
main3 = putStrLn $ fmap show $ fmap getit good
main2失败:
• No instance for (Show (IO Int)) arising from a use of ‘show’
• In the second argument of ‘($)’, namely ‘show $ fmap getit good’
In a stmt of a 'do' block: putStrLn $ show $ fmap getit good
In the expression: do { putStrLn $ show $ fmap getit good }
和main3失败了:
• Couldn't match type ‘IO’ with ‘[]’
Expected type: String
Actual type: IO String
习惯重写的正确方法是什么?
(子问题:是"&lt; - "这个家伙实际上称为bind?通过此处:通用haskell操作员是否有明显的名称?)
do
中的变量绑定 - 通知 bind bind combinator >>=
:
do { x <- m ; rest } = m >>= x -> do rest
所以您的示例转换为:
main = fmap getit good >>= x -> putStrLn $ show x
或以无点样式的方式:
main = fmap getit good >>= putStrLn . show
或利用fmap
和>>=
之间的关系:
main = good >>= putStrLn . show . getit
对于许多单子,最后形式将更有效。fmap
通常必须重建映射的结构(例如,列表的fmap
在O(n)时间中运行),而功能组成始终为O(1)。
self,当您搜索搜索如何发音时"&lt; - "您发现我认为您正在寻找:
main4 :: IO ()
main4 = (fmap show $ fmap getit good) >>= putStrLn
从这里:
https://wiki.haskell.org/io_inside
一个更复杂的示例涉及使用"&lt; - "的变量结合:
main = do a&lt; - readln 打印A此代码分为:
main = readln
>>=
( A->打印A)
但是@benjamin Hodgson的答案更好,尤其是根本不需要FMAP的版本。
和子问题"&lt; - " desugars绑定,但发音为" to":https://wiki.haskel.org/pronunciation