Applicative <*> inside ReaderT StateT IO

Applicative <*> inside ReaderT StateT IO

在 ReaderT StateT IO do 块中,我正在尝试使用 <*> 在 Maybe 中调用带有 Maybe 参数的函数,但这会导致类型错误。

onMessage <*> (message update)

如果我使用 return $ onMessage <*> (message update) 包装表达式,它会进行类型检查,但函数似乎不会被求值。

如果我同时解包函数和参数并手动检查 Nothing 函数会被调用,但这看起来很难看。

在此上下文中是否有其他运算符可以使用?这些是我的第一个 Monad Transformer 步骤,类型太复杂了,甚至无法尝试 hoogle 一个答案。


...

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

根据你的说法,我了解到:

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

如果是 Just,要执行封闭的 Bot a () 计算,您可以使用:

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

更新

这个 "force" 包装的 Bot a () 计算的评估如何?

我们知道 onMsg <*> ...NothingJust comp,其中 compBot a () 计算。

comp 将是 "evaluated" 如果它成为 do 块中的单子序列的一部分。

上面的代码是一样的:

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

因此 return ()comp 将是 do 块中的下一步。