On advice I received here, I am trying to rewrite a function without an extraneous bind assignment and return, but am getting stuck with an extra IO I can't seem to understand how to get out of it.
I have
good :: IO (Either Int String)
getit :: Either Int String -> Int
main :: IO ()
main = do
x <- fmap getit good
putStrLn $ show x
main works fine. But....
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 fails with:
• 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 }
And main3 fails with:
• Couldn't match type ‘IO’ with ‘[]’
Expected type: String
Actual type: IO String
What's the correct way to rewrite this idiomatically?
(Sub-question: is "<-" this guy actually called a bind? via here: Are there pronounceable names for common Haskell operators? )
Variable-binding in
do-notation desugars into calls to the bind combinator>>=:So your example translates to:
Or, in point-free style:
Or, exploiting the relationship between
fmapand>>=:For many monads this last form will be more efficient.
fmapoften has to rebuild the mapped structure (for example, lists'fmapruns in O(n) time) whereas function composition is always O(1).