gpt4 book ai didi

haskell - 当 Exc 是成员时 Control.Eff 的 MonadPlus 实例

转载 作者:行者123 更新时间:2023-12-01 12:38:55 28 4
gpt4 key购买 nike

monad transformers , 我们有

instance (Monad m, Monoid e) => MonadPlus (ExceptT e m)

extensible effects , 没有这样的东西

instance (Monoid e) => MonadPlus (Eff (Exc e :> r))

我试过实现它,但没有成功。这是我目前所拥有的:

instance (Monoid e) => MonadPlus (Eff (Exc e :> r)) where
mzero = throwExc mempty
a `mplus` b = undefined $ do
resultA <- runExc a
case resultA of
Left l -> runExc b
Right r -> return $ Right r

有两个问题:

  • mzero , GHC 提示如下:

    Could not deduce (Monoid e0) arising from a use of ‘mempty’
    from the context (Monad (Eff (Exc e :> r)), Monoid e)

    为什么 GHC 不匹配 e0e

    答案(在评论中提供):开启ScopedTypeVariables

  • mplus , undefined应替换为 runExc 的反函数,但我在可扩展效果的 API 中找不到它。我错过了什么吗?

理由:我希望能够写出a <|> bMember (Exc e) r => Eff r a 内, 意思是:

  • 尝试 a
  • 如果a抛出 ea , 尝试 b
  • 如果b抛出 eb , 然后抛出 mappend ea eb

这需要 Alternative例如,这就是为什么我要尝试实现 MonadPlus首先是实例。

注意:我使用的是 GHC 7.8.3。

预先感谢您的帮助。

最佳答案

我认为您可能对可扩展效果和所需的效果感到困惑实例 MonadPlus (Eff (Exc e :> r))显示困惑。

如果你想构建一个非确定性计算并抛出异常(exception)情况,您已经可以做到这一点而无需新的实例。我想我可能对以下的困惑负部分责任定义完全等同于的单独的 mzero' 和 mplus'那些在 MonadPlus 中的。无论如何,由于这种等价性,你可以简单地写

instance Member Choose r => MonadPlus (Eff r) where
mzero = mzero'
mplus = mplus'

实例说:具有选择效果的计算,其中其他,是 MonadPlus 计算的一个实例。让我强调“除其他外”部分。计算可能会产生其他影响,例如,抛出异常。上面的 MonadPlus 实例涵盖了这种情况,以及所有其他情况。

因此,要使用非确定性和异常,您只需使用 mplus、mzero(或 mplus'、mzero')以及 throwExc。无需定义任何新实例 - 与 Monad 变形金刚形成鲜明对比。

当然,您必须决定您希望异常如何交互具有不确定性:异常应该丢弃所有选择还是仅丢弃剩下的选择?这取决于您如何订购处理程序,效果首先得到处理。此外,您可以为两者编写一个处理程序选择和 Exc 效果(将已经做出的选择保留在异常并丢弃剩余的——从而对 Prolog 的切割进行建模)。库的代码(以及论文随附的代码)有这方面的示例。

编辑以回复修改后的问题:如果您只需要 <|> ,它可以简单地实现,无需 MonadPlus 或 cut。这个运算符仅仅是异常处理的一种形式,并且可以作为两个catchError的组合。这是完整的代码

alttry :: forall e r a. (Typeable e, Monoid e, MemberU2 Exc (Exc e) r) =>
Eff r a -> Eff r a -> Eff r a
alttry ma mb =
catchError ma $ \ea ->
catchError mb $ \eb -> throwError (mappend (ea::e) eb)

如果计算 ma 成功完成,则返回其结果。否则,mb 已尝试;如果成功完成,则返回其结果。如果两者都失败,引发了 mappend-ed 异常。代码直接匹配英文规范。

我们在签名中使用 MemberU2 而不是 Member 来确保计算仅抛出一种类型的异常。否则,这个构造不是很有用。我使用了原始实现 Eff.hs .该文件还包含测试用例。

顺便说一句,没有可扩展的效果需要定义或使用类型类,如 MonadPlus、MonadState 等。这些类型类旨在隐藏 MonadTransformer 堆栈的具体布局。有了可扩展的效果,就没有什么可隐藏的了。不再需要拐杖。

关于haskell - 当 Exc 是成员时 Control.Eff 的 MonadPlus 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26876385/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com