1
votes

Inside a ReaderT StateT IO do block I am trying to call a function inside a Maybe with a Maybe parameter using <*> but that results in a type error.

onMessage <*> (message update)

If I wrap the expression using return $ onMessage <*> (message update) it type checks but then the function does not appear to be evaluated.

If I unwrap both the function and the argument and check for Nothing manually the function is called but that seems ugly.

Is there another operator to use in this context? These are my first Monad Transformer steps and the types are too perplexing to even try and hoogle an answer.


...

type Bot a = ReaderT (BotConfig a) (StateT (BotState a) IO)

...

processUpdate :: Update -> Bot a ()
processUpdate update = do
    BotConfig {tw_handlers = MessageHandlers {
          tw_onMessage = onMg
        }
    } <- ask

    onMg <*> (message update) -- this is what I would like to do
                              -- onMg :: Maybe (Message -> Bot a ())
                              -- message :: Update -> Maybe Message
1
Can you provide a small code snippet with the actual types? It's hard to understand as it is.chi
Hi Chi. Please see the code above.hcvst
Perhaps wrapping it with return is ok. The question then is how to force evaluation I tried seq, which didn't help and seqdeep which resulted in type errors again.hcvst

1 Answers

2
votes

From what you say, I understand that:

onMsg <*> (message update) :: Maybe ( Bot a () )

To execute the enclosed Bot a () computation if it is a Just, you can use:

maybe (return ()) id $ onMsg <*> (message update)

Update

How does this "force" evaluation of the wrapped Bot a () computation?

We know that onMsg <*> ... is either Nothing or Just comp where comp is a Bot a () computation.

comp will be "evaluated" if it becomes part of the monadic sequence in the do-block.

The code above is the same as:

case (onMsg <*> ...) of
  Nothing    -> return ()
  Just comp  -> comp

So either return () or comp will be the next step in the do-block.