首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Transformers下的转换

Transformers下的转换
EN

Stack Overflow用户
提问于 2013-05-15 04:31:11
回答 1查看 162关注 0票数 7

目前我在使用monad transformers时遇到了一些困难。我正在定义一些不同的非确定性关系,这些关系利用了转换器。不幸的是,我很难理解如何清晰地从一个有效的模型转换到另一个有效的模型。

假设这些关系是"foo“和"bar”。假设"foo“与As相关,Bs与Cs相关;假设"bar”与Bs相关,Cs与Ds相关。我们将根据"foo“来定义"bar”。更有趣的是,这些关系的计算将以不同的方式失败。(由于bar关系依赖于foo关系,因此它的失败案例是一个超集。)因此,我给出了以下类型定义:

代码语言:javascript
复制
data FooFailure = FooFailure String
data BarFailure = BarSpecificFailure | BarFooFailure FooFailure
type FooM = ListT (EitherT FooFailure (Reader Context))
type BarM = ListT (EitherT BarFailure (Reader Context))

然后,我希望能够使用以下函数签名来编写关系:

代码语言:javascript
复制
foo :: A -> B -> FooM C
bar :: B -> C -> BarM D

我的问题是,在编写"bar“的定义时,我需要能够从"foo”关系中接收错误,并在"bar“空间中正确地表示它们。所以我可以使用表单的一个函数

代码语言:javascript
复制
convert :: (e -> e') -> ListT (EitherT e (Reader Context) a
                     -> ListT (EitherT e' (Reader Context) a

我甚至可以通过运行ListT,在EitherT上映射,然后重新组装ListT来编写这个小野兽(因为碰巧可以将m a转换为ListT m a)。但这似乎..。一团糟。

我有一个很好的理由,我不能只运行一个转换器,在它下面做一些事情,然后一般地“把它放回去”;我运行的转换器可能会有影响,但我不能神奇地撤销它们。但是,有没有什么方法可以将一个函数提升到转换器堆栈中足够远的地方,以便为我做一些工作,这样我就不必编写上面所示的convert函数了?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-05-15 07:52:59

我认为convert是一个很好的答案,并且使用Control.Monad.MorphControl.Monad.Trans.Either编写它(几乎)真的很简单:

代码语言:javascript
复制
convert :: (Monad m, Functor m, MFunctor t)
           => (e -> e')
           -> t (EitherT e m) b -> t (EitherT e' m) b
convert f = hoist (bimapEitherT f id)

小问题是ListT不是MFunctor的实例。我认为这是作者抵制ListT的原因,因为它是doesn't follow the monad transformer laws的,因为它很容易编写类型检查实例

代码语言:javascript
复制
instance MFunctor ListT where hoist nat (ListT mas) = ListT (nat mas)

无论如何,总体上看一下用于处理transformer堆栈(部分)上的自然转换的Control.Monad.Morph。我想说,这符合将一个函数“恰到好处”提升到堆栈中的定义。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16552316

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档