I don't understand why this happens:
module Main where
import Control.Monad.Reader
data Config = Config Int
getA :: (Monad m) => ReaderT Config m Int
getA = do
Config a <- ask
return a
readConfig :: Config -> IO Int
readConfig config = do
a <- runReaderT getA config
return a
main :: IO ()
main = do
print "Start"
let a = Config 2
b <- readConfig a -- Will be printed
print b
let c = Config 4
print <$> initConfig c -- Silence, nobody complains..
print "Done"
the result is just:
"Start"
2
"Done"
Why is print <$> readConfig a
empty? Even with -Wall
nobody complains about this...
(I tried diff ghc versions in godbolt but the result stays the same)
CodePudding user response:
GHC 8.10.3 does complain about this with -Wall (after I changed initConfig
to readConfig
in your code):
A do-notation statement discarded a result of type ‘IO ()’
Suppress this warning by saying ‘_ <- print <$> readConfig c’
You have readConfig c
of type IO Int
. Then you fmap print
, giving something with a type of IO (IO ())
. Since the result isn't bound to a variable in the do block, it is thrown away.
In the fmap's type Functor f => (a -> b) -> f a -> f b
we have f
being IO
, a
being Int
, and b
being IO ()
. So it is used with the type (Int -> IO ()) -> IO Int -> IO (IO ())
.
This would work:
printAction <- print <$> readConfig c
printAction
But what you actually want is a bind:
print =<< readConfig c