Haskell函数重写而无需绑定返回



在我在这里收到的建议下,我试图在没有外部绑定和返回的情况下重写功能,但是我似乎无法理解如何获得额外的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

最新更新