【问题标题】:Applicative <*> inside ReaderT StateT IOReaderT StateT IO 中的应用 <*>
【发布时间】:2016-06-05 10:45:50
【问题描述】:

在 ReaderT StateT IO do 块内我尝试使用 &lt;*&gt; 使用 Maybe 参数调用 Maybe 内的函数,但这会导致类型错误。

onMessage &lt;*&gt; (message update)

如果我使用 return $ onMessage &lt;*&gt; (message update) 包装表达式,它会进行类型检查,但函数似乎没有被计算。

如果我解开函数和参数并手动检查Nothing,则调用该函数,但这看起来很难看。

在这种情况下还有其他运算符可以使用吗?这些是我的第一个 Monad Transformer 步骤,这些类型太令人困惑,甚至无法尝试和胡扯一个答案。


...

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

【问题讨论】:

  • 你能提供一个带有实际类型的小代码sn-p吗?这很难理解。
  • 嗨志。请看上面的代码。
  • 也许用 return 包装它是可以的。然后的问题是如何强制评估我尝试了 seq,但没有帮助,而 seqdeep 再次导致类型错误。

标签: haskell monad-transformers


【解决方案1】:

根据你的说法,我明白:

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

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

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

更新

如何“强制”评估封装的 Bot a () 计算?

我们知道onMsg &lt;*&gt; ...NothingJust comp,其中compBot a () 计算。

如果comp 成为 do-block 中单子序列的一部分,它将被“评估”。

上面的代码同:

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

所以return ()comp 将是执行块中的下一步。

【讨论】:

  • 谢谢。那解决了它。我还是有点困惑。查看maybe 文档,它说“可能函数采用默认值、函数和可能值。”所以这里(return ()) 是默认值,id $ onMsg &lt;*&gt; 部分应用函数和(message update) 值?您是否使用 id 来强制评估?
  • 默认值为return () - Bot a 动作;函数是id; Maybe 值是 onMsg &lt;*&gt; (message update)
  • 作为次要选择,fromMaybe (return ()) $ onMg &lt;*&gt; (message update)
  • @hcvst - 更新答案以解释这种“强制”评估的方式。
  • 非常感谢@ErikR。也感谢 chi 的替代品。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 2018-12-03
相关资源
最近更新 更多