【问题标题】:Combining Either and Pair monads with transformers将 Either 和 Pair monad 与转换器结合
【发布时间】:2017-06-07 04:18:08
【问题描述】:

我以前没有使用过 monad 转换器,但我认为这是我需要的。下面是一些示例代码:

Prelude> (+) <$> Right 2 <*> Right 3
Right 5

Prelude> (+) <$> (['a'],2) <*> (['b'],3)
("ab",5)

但我想像这样结合这两种行为:

Prelude> (+) <$> Right ("a",2) <*> Right ("b",3)
Right ("ab",5)

这自然无法编译,因为(String, Int) 上没有定义数字加法。

Monad transformers Haskell wiki page 建议我需要为内部 monad 使用转换器,在本例中是一对,但在 Hayoo!Hoogle 上搜索 PairT 并没有发现任何相关信息。

我必须自己实现这个转换器,还是我错过了关于 Hackage 的一些东西,或者我只是误解了应该如何做?

注意:

我使用的实际外部 monad 不是 Either,它是我在此 question 中详述的自定义 monad,但它与 Either 非常相似。

【问题讨论】:

    标签: haskell monads monad-transformers


    【解决方案1】:

    在示例中,我们以“应用”方式组合动作,这意味着每个动作不依赖于前一个动作的返回值。

    事实证明Applicatives 比Monads 组合更好:我们不需要为每个Applicative 使用不同的“转换器”类型,而是可以使用一个通用的Compose newtype 来为任意两个创建一个复合效果Applicatives:

    ghci> import Data.Functor.Compose
    ghci> getCompose $ (+) <$> Compose (Right ("a",2)) <*> Compose (Right ("b",3))
    Right ("ab",5)
    

    “最外层”Applicative(本例中为Either)的效果具有优先权。

    新类型的包装/展开时有一些噪音。如果我们想避免 newtype 噪音和操作符,我们还可以修改 chi 的答案并做类似

    liftA2 (liftA2 (+)) (Right ("a",2)) (Right ("b",3))
    

    “外部”liftA2 作用于Either,“内部”liftA2 作用于(,) String

    【讨论】:

      【解决方案2】:

      另一种选择:

      > liftA2 (+) <$> Right ("a",2) <*> Right ("b",3)
      Right ("ab",5)
      

      【讨论】:

        【解决方案3】:

        在这里回答我自己的问题,我认为 Pair monad 转换器是WriterT。在上面的示例中,您要查找的类型是

        WriterT String (Either l) Int
        

        String 应替换为对右侧的任何内容。
        l 应为 Left 的类型。
        Int 应替换为结果类型是。

        【讨论】:

        • 谨慎使用WriterT String。首先记住String = [Char],所以列表的幺半群实例适用。对于列表,mappend = (++)。请记住,n ++ m 具有运行时复杂性:O(n)。当你一遍又一遍地这样做时,复杂性就变成了O(n^2)。因此,您应该改用差异列表:kseo.github.io/posts/…
        • 另外,鉴于Either e a = Except e a = ExceptT e Identity a 请注意WriterT w (Except e) /= ExceptT e (Writer w)。前者有异常时没有日志,后者始终有日志,即使发生异常。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-02-09
        • 1970-01-01
        • 2021-01-04
        • 2020-11-16
        • 2021-03-14
        • 2011-11-17
        • 1970-01-01
        相关资源
        最近更新 更多