Haskell函数重写没有绑定返回

Mit*_*ops 1 haskell pointfree

根据我在这里收到的建议,我试图在没有无关的绑定分配的情况下重写函数并返回,但是我遇到了额外的IO,我似乎无法理解如何摆脱它.

我有

good :: IO (Either Int String)

getit :: Either Int String -> Int

main :: IO ()
main = do
  x <- fmap getit good
  putStrLn $ show x
Run Code Online (Sandbox Code Playgroud)

主要工作正常.但....

main2 :: IO ()
main2 = do
  putStrLn $ show $ fmap getit good

-- let's try totally without do
main3 :: IO ()
main3 = putStrLn $ fmap show $ fmap getit good
Run Code Online (Sandbox Code Playgroud)

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 }
Run Code Online (Sandbox Code Playgroud)

并且main3失败了:

• Couldn't match type ‘IO’ with ‘[]’
  Expected type: String
    Actual type: IO String
Run Code Online (Sandbox Code Playgroud)

用这个惯用法重写这个的正确方法是什么?

(子问题:是"< - "这家伙实际上称之为绑定?通过这里:常见的Haskell运营商是否有明显的名称?)

Ben*_*son 5

变量绑定do注释desugars到bind组合器的调用>>=:

do { x <- m ; rest }  =  m >>= \x -> do rest
Run Code Online (Sandbox Code Playgroud)

所以你的例子转换为:

main = fmap getit good >>= \x -> putStrLn $ show x
Run Code Online (Sandbox Code Playgroud)

或者,无点样式:

main = fmap getit good >>= putStrLn . show
Run Code Online (Sandbox Code Playgroud)

或者,利用之间的关系fmap>>=:

main = good >>= putStrLn . show . getit
Run Code Online (Sandbox Code Playgroud)

对于许多monad来说,这最后一种形式会更有效率.fmap通常必须重建映射结构(例如,列表fmap在O(n)时间内运行),而函数组合总是O(1).