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
fmap
and>>=
:For many monads this last form will be more efficient.
fmap
often has to rebuild the mapped structure (for example, lists'fmap
runs in O(n) time) whereas function composition is always O(1).