haskellmonadsreader-monad

How to use mapReader from Control.Monad.Reader for reader monad?


I am trying to figure out that how to use mapReader from Control.Monad.Reader.

For example I have this reader monad

myReaderMonad :: Reader String Int
myReaderMonad = do
  string <- ask
  return (length string)

I can run it like this

>>> runReader myReaderMonad  "Saurabh"
>>> 7

Now I am trying to check the value returned by runReader is even or not. Without using mapReader I can do like this

>>> even $ runReader myReaderMonad  "Saurabh"
>>> False

But I want to do this by using mapReader https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html#v:mapReader

I tried the following but it is not working.

>>> mapReader even  myReaderMonad  "Saurabh"
>>> • Couldn't match expected type ‘[Char] -> t’
                  with actual type ‘ReaderT
                                      String Data.Functor.Identity.Identity Bool’
    • The function ‘mapReader’ is applied to three arguments,
      but its type ‘(Int -> Bool)
                    -> Reader String Int
                    -> ReaderT String Data.Functor.Identity.Identity Bool’
      has only two
      In the expression: mapReader even myReaderMonad "Saurabh"
      In an equation for ‘it’:
          it = mapReader even myReaderMonad "Saurabh"

Please help me here.


Solution

  • mapReader doesn't suddenly turn your Reader-computation into a plain function, it just turns it into another Reader-computation.

    The expression mapReader even myReaderMonad doesn't return a function to which you could feed "Saurabh" as an argument. Instead, it gives you a Reader String Bool.

    Now that you have this new Reader String Bool value, you can give it a string using runReader and obtain a result:

    > myEvenReader = mapReader even myReaderMonad
    ...
    > runReader myEvenReader "Saurabh"
    False
    

    Or you can use it in some other way, for example put it through another mapReader:

    > myOddReader = mapReader not myEvenReader
    ...
    > runReader myOddReader "Saurabh"
    True