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 <*> ...
是 Nothing
或 Just comp
,其中 comp
是 Bot a ()
计算。
comp
将是 "evaluated" 如果它成为 do 块中的单子序列的一部分。
上面的代码是一样的:
case (onMsg <*> ...) of
Nothing -> return ()
Just comp -> comp
因此 return ()
或 comp
将是 do 块中的下一步。
在 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 <*> ...
是 Nothing
或 Just comp
,其中 comp
是 Bot a ()
计算。
comp
将是 "evaluated" 如果它成为 do 块中的单子序列的一部分。
上面的代码是一样的:
case (onMsg <*> ...) of
Nothing -> return ()
Just comp -> comp
因此 return ()
或 comp
将是 do 块中的下一步。