mtl,transformers,monads-fd,monadLib和选择的悖论


92

黑客有几个用于monad变压器的软件包:

  • mtl:Monad变压器库
  • 变压器:混凝土函子和单子变压器
  • monads-fd:Monad类,使用函数依赖项
  • monads-tf:Monad类,使用类型族
  • monadLib:monad变压器的集合。
  • mtl-tf:使用类型族的Monad转换器库。
  • mmtl:模块化Monad变压器库
  • mtlx:具有类型索引的Monad转换器库,提供“免费”副本。
  • compose-trans:可组合的monad变压器

(也许我错过了一些)

我们应该使用哪一个?

mtl是Haskell平台中的mtl,但我一直在reddit上听到它很不酷的消息。

但是无论如何,选择有什么不好,这不是一件好事吗?

好吧,我看到例如数据访问器的作者必须如何做出所有这些选择以迎合流行的选择:

  • data-accessor-monadLib库:monadLib的monad的访问器函数
  • data-accessor-monads-fd库:使用访问器访问monads-fd State monad类中的状态
  • data-accessor-monads-tf库:使用访问器访问monads-tf State monad类型族中的状态
  • data-accessor-mtl库:使用访问器访问mtl State monad类中的状态
  • data-accessor-transformers库:使用Accessor来访问变形金刚状态monad中的状态

我想如果继续进行下去,例如几个竞争的Arrow软件包不断发展,我们可能会看到类似的东西:spoonklink-arrows-transformers,spoonklink-arrows-monadLib,spoonklink-tfArrows-transformers,spoonklink-tfArrows-monadLib,...

然后,我担心如果spoonklink被派生了,黑客程序将耗尽磁盘空间。:)

问题:

  • 为什么会有这么多的monad变压器套件?
  • 为什么[考虑]不酷?
  • 主要区别是什么?
  • 这些看似竞争的软件包中的大多数由Andy Gill编写,由Ross Paterson维护。这是否意味着这些软件包没有竞争,而是以某种方式协同工作?Andy和Ross是否认为自己的任何软件包都已过时?
  • 您和我应该使用哪一个?

2
该链接帮助我了解了MTL
Brandon Cook

2
向下滚动以获取@jberryman评论!使用mtl或transfomers,它们变得兼容!
索菲(Sophie)

Answers:


70

其中一堆几乎完全等效:

  • mtl使用GHC扩展名,但是transformers是Haskell 98。
  • monads-fd并且monads-tf是的附加组件transformers,分别使用功能依赖项和类型族,两者都提供mtl缺少的功能transformers
  • mtl-tfmtl使用类型的家庭重新实现。

所以本质上mtl== transformers++ monads-fdmtl-tf== transformers++ monads-tf。我认为,如今改进的可移植性和模块化transformers以及与其相关的软件包是为什么mtl现在不那么酷的原因。

mmtl并且mtlx两者似乎都与和/或基于mtl,但具有API区别和额外功能。

MonadLib似乎在事情上截然不同,但我对它并不直接熟悉。似乎还使用了许多GHC扩展,而不是其他。

乍一看compose-trans似乎更像是用于创建monad转换器的元编程内容。它声称与Control.Monad.Trans... 兼容mtl什么?

无论如何,我建议使用以下决策算法:

  • 您需要新项目的标准monad吗?使用transformers&co。,帮助我们躺下mtl休息。
  • 您已经mtl在大型项目中使用了吗?transformers并非完全兼容,但没有人会因为不切换而杀死您。
  • 其他软件包之一是否提供所需的非常规功能?最好使用它,而不要自己动手。
  • 还是不满意?category-extras用一页半的令人费解的抽象废话惊人的通用代码将它们全部扔掉,下载并解决世界上所有的问题。

2
如果mtl ==变形金刚++ monads-fd,难道不是只能以这种方式实现吗?(作为替换它的阶段)将不需要像data-accessor-mtl这样的东西
yairchu 2010年

2
@yairchu:是的,但是您希望我对此做些什么?:)保持向后兼容性从未像看起来那样容易,并且更改密钥库需要时间,精力和某种程度的社区支持。monad变压器的情况是一个已知问题,但我认为从长远来看,这不是任何人的头等大事。
加利福尼亚州麦肯

5
@yairchu:基本上就是正在做的事情。Mtl的下一个主要版本应该是导入translators + monads-fd的存根,并且与该版本的兼容性将成为决定性因素。然后,可以对库进行单独更新,以使其与mtl 1.1和1.2兼容,然后将应用程序归类为已安装的版本或限制性最强的库依赖项所要求的版本。
爱德华·KMETT

2
图书馆的邮件列表目前正在讨论将MonadIO(以及可能的MonadTrans移出mtl并移入基本库)的问题。尽管“ MonadBase”需要MPTC,fundeps等事实,但仍在提取MonadIO还是更通用的MonadBase挂了。
爱德华KMETT

27
自从我发现这篇文章非常有用。我以为我会更新其他的googlers:mtl现在依赖于变压器,monads-fd现在是mtl周围的存根。因此,如果需要额外的东西,请使用mtl;如果具有所需的一切,则只需导入变压器。
jberryman 2011年

20

现在呢?您可能应该使用mtl。正在发生的事情是,transformers图书馆是在被时尚的因素母语指出,monads-fdmonads-tf可以和平共存,但最后的支票,还没有的情况。

发生这种情况时,您将能够导入monads-fdtransformers获取(几乎)相同的接口,但State等等将是的别名StateT

因此,我会写信给mtl,但不要依赖于State,Reader等当前data被使用types 代替的事实。

MonadLib 是Iavor一直在努力的另一个选择,可以安全地使用它,因为它不与其他模块共享任何模块名称,但是使用模式却大不相同。


4
在什么意义上并存?用于同一包装?导入到同一个模块中?合并到同一变压器堆栈中?总的来说,混合使用二头肌和TF会让我感到一个坏主意。无论如何,我并没有广泛使用transformers&co。但是,除了mtl切换一些(相当简单的)代码时,除了一些微小的API差异外,没有发现任何其他问题。
CA McCann

4
问题归结为您只能加载提供给定模块的一个软件包这一事实。因此,如果您使用甚至在内部使用mtl的库,也无法导入替代方法。当前,健康百分比的黑客以某种方式在内部使用了MTL。许多人更喜欢使用类型家族,而monads-tf则为他们提供了这种类型,但请记住,目前,在完成转换器+ monads-fd重构之前,此锁定可防止使用任何需要传递MTL的库。这包括一些相当大的门票项目。
爱德华·KMETT

1
从长远来看,使用transformers + monads-(tf | fd)可以避免该泡菜,但我们还没有。同时,用法的主要优势是mtl。升级路径似乎是将Mtl的下一个主要版本重新定义为导入monads-fd和转换器的存根。主版本中断提供了一种很好的方式,可以在阴谋文件中声明您不在乎获得哪个版本(即,您不在乎State是类型别名还是数据类型),一旦发生主版本冲突,便可以您不必担心您使用的每个库是否都具有相同的偏见。
爱德华·KMETT

1
因此,到目前为止,最终您的经验恰好是设计的变形金刚/ monads-(tf | fd)支持的。但是,在写完这些书后才意识到,当社区没有令人信服的理由跳楼而留下大量遗留的理由时,社区在切换图书馆方面就显得非常糟糕。因此,需要重新定义mtl并弄清楚升级路径。
爱德华·KMETT

太好了,谢谢您的详细说明!显然,我切换的代码几乎没有外部依赖关系,我认为主要是FFI绑定。我也没有意识到模块名称冲突是...侵入性的,我猜是吗?确实确实使事情变得尴尬。:(
CA McCann

16

Edward Kmett在回答中提到的分解因素已于2010年底完成。其最终结果是基于变压器的monads-fd,成为mtl的版本2 。由于mtl的普遍存在,monads-tf从未真正流行起来。截至2017年初,MTLTransformer是唯一被广泛使用的monad变压器库。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.