haskell - 是否可以在单子(monad)序列中更改单子(monad)类型?

标签 haskell monads either

我知道可以更改包装类型,以便您可以拥有

f :: (a -> m b)
g :: (b -> m c)
f >>= g :: (a -> m c)

但是可以更改m ?如果 mMonadError并由 Either ErrorA 实现和 Either ErrorB ,我可以以某种方式链接它们吗?显然我不能直接链接它们,因为 Left 的类型是什么? ?但是,我遇到的情况是我最终调用了show。在任何一种情况下,但我还没有找到比
case mightFail1 of
  Left e -> show e
  Right v -> either show doStuff mightFail2

它无法正确使用在第一个错误处停止的单子(monad)行为,而无需我进行明确检查。

最佳答案

“改变容器”的整个概念被称为“自然转换”。具体来说,我们想要一个在不影响内部内容的情况下转换容器的函数。我们可以通过使用 forall 来确保类型系统中的情况。 .

-- natural transformation
type (m :~> n) = forall a. m a -> n a

然后可以随时应用这些。例如,如果您可以转换 ErrorA -> ErrorB然后有一个通用的操作给你
mapE :: (e -> e') -> (Either e :~> Either e')
mapE f (Left e)  = Left (f e)
mapE _ (Right a) = a

您甚至可以对类型运算符和求和类型非常感兴趣。
-- a generic sum type
infixr 9 :+:
newtype (a :+: b) = Inl a | Inr b

liftE :: (Either e :~> Either (e' :+: e))
liftE = mapE Inr

双仿函数实现了大致相同的效果,但它们是看待问题的完全不同的方式。它们通常不会改变容器,而是影响容器本身的另一个协变参数(或索引)。因此,Bifunctor Action 总是可以看作是自然变换,但 NT 更一般。

关于haskell - 是否可以在单子(monad)序列中更改单子(monad)类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18066113/

相关文章:

scala - 用于理解 if 守卫

parsing - Haskell Parsec - 使用自定义 token 时错误消息的帮助不大

在 Haskell 的 Parsec 中解析基于缩进的语法

haskell - 使用 Control.Concurrent.STM.TBQueue 时的内存泄漏

Haskell 处理 [IO 字符串]

Haskell - 使用 Reader monad 的二叉树中每个节点的深度

scala - 如何使用 `asRight` 创建带有猫的 Either 实例

haskell - 编译器优化后如何分析 Haskell?

OCaml:更高种类的多态性(对模块进行抽象?)

验证与析取