Search code examples
haskellmonad-transformersoption-typewriter-monad

Wrapping Maybe in WriterT to add logging


I'm totally stuck and I feel like I can use some help now, just to stay sane. I want something as simple as adding logging capabilities to a function that returns Maybe, but no matter how hard I try I just can't get the types right.

This is (as I perceive it) the closest I could get:

import Data.Maybe
import Control.Monad
import Control.Monad.Writer

q :: Integer -> Maybe Integer
q x = if x > 7
      then Just x
      else Nothing

qlog :: Integer -> WriterT [String] Maybe Integer
qlog x = do
  tell ["Querying " ++ show x]
  return $ q x

Which still yields me a typing error:

Couldn't match type ‘Maybe Integer’ with ‘Integer’
Expected type: WriterT [String] Maybe Integer
  Actual type: WriterT [String] Maybe (Maybe Integer)
In a stmt of a 'do' block: return $ q x
In the expression:
  do { tell ["Querying " ++ show x];
       return $ q x }
In an equation for ‘qlog’:
    qlog x
      = do { tell ["Querying " ++ show x];
             return $ q x }

How should I adjust the code to make it compile and work?

Thank you so much for your help, fellow Haskellers!


Solution

  • In order to type-check, inner monads should be lifted:

    lift :: (Monad m, MonadTrans t) => m a -> t m a
    

    So, instead of return $ q x you need to write: lift $ q x; as in:

    qlog :: Integer -> WriterT [String] Maybe Integer
    qlog x = do
      tell ["Querying " ++ show x]
      lift $ q x