Home > Enterprise >  Value is discarded in Haskell
Value is discarded in Haskell

Time:10-09

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
  • Related