Fmap putStrLn getLine does not do IO

The title said everything, in fact. I cannot understand why this following code does not actually print “Hello World”, and not what it does >>=.

main = fmap putStrLn getLine

Right now, here is my line of reasoning, please check if it has any error.

If compared fmapwith>>=

(>>=) :: Monad m => m a -> (a -> m b) -> m b
fmap :: Functor f => (a -> b) -> f a -> f b

In bind, context, or in terms of IO "World", the first mand second are mcompletely different from the types. (a -> m b)essentially recreates a new "World." This is not true in Functor, the context fis the same, therefore side effects are impossible.

Now, if this is true, why does the compiler not give a warning when we try to perform fmapefficient I / O on an existing IO Monad?

+4
source share
1 answer

You are almost there. What is the type fmap putStrLn?

putStrLn      ::              String -> IO ()
fmap          :: Functor f => (a -> b) -> f a -> f b    
fmap putStrLn :: Functor f => f String -> f (IO ())

And the result fmap putStrLn getLinewill be IO (IO ()), that is, an IO action that contains another IO action. There is no need for warning * in the end, it may be what you intended. The compiler cannot determine if you want m (m a)or m a.

Actually the power of the monad, it has an operation that allows you to join these actions:

join :: Monad m => m (m a) -> m a
-- join x = x >>= id

*, , , . GHC, , -fwarn-missing-signatures. . .

+13

All Articles