Mtl、变压器、 monads-fd、 monadLib 和选择悖论

Hackage 为单子变压器提供了几个软件包:

(也许我错过了一些)

我们用哪一个?

Mtl 是 Haskell 平台上的那个,但我一直在 Reddit 上听说它不酷。

但是选择有什么不好的呢,难道不是件好事吗?

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

  • Data-Accessor-monadLib 库: monadLib 单子的访问器函数
  • Data-Accessor-monads-fd 库: 使用 Accessor 访问 monads-fd State monad 类中的状态
  • Data-Accessor-monads-tf 库: 使用 Accessor 访问 monads-tf State monad 类型族中的状态
  • Data-Accessor-mtl 库: 使用 Accessor 访问 mtl State 单子类中的状态
  • 数据访问器-变压器库: 使用访问器访问变压器状态单子中的状态

我猜想,如果这种情况继续下去,例如,几个竞争的 Arrow 软件包发展,我们可能会看到这样的东西: spoonklink-Arrow-formers,spoonklink-Arrow-monadLib,spoonklink-tfArrows-formers,spoonklink-tfArrows-monadLib,... ..。

然后我担心,如果 Spoonklink 被分叉,Hackage 将耗尽磁盘空间。 :)

问题:

  • 为什么有这么多 monad transformer 包裹?
  • 为什么 mtl [被认为]不酷?
  • 主要区别是什么?
  • 这些看似相互竞争的软件包大多由 Andy Gill 编写,Ross Paterson 负责维护。这是否意味着这些方案不是相互竞争,而是以某种方式协同工作?安迪和罗斯认为他们自己的套餐过时了吗?
  • 我们应该用哪一个?
7712 次浏览

A bunch of them are almost completely equivalent:

  • mtl uses GHC extensions, but transformers is Haskell 98.
  • monads-fd and monads-tf are add-ons to transformers, using functional dependencies and type families respectively, both providing the functionality in mtl that's missing from transformers.
  • mtl-tf is mtl reimplemented using type families.

So essentially, mtl == transformers ++ monads-fd, mtl-tf == transformers ++ monads-tf. The improved portability and modularity of transformers and its associated packages is why mtl is uncool these days, I think.

mmtl and mtlx both seem to be similar to and/or based on mtl, with API differences and extra features.

MonadLib seems to have a rather different take on matters, but I'm not familiar with it directly. Also seems to use a lot of GHC extensions, more than the others.

At a glance compose-trans seems to be more like metaprogramming stuff for creating monad transformers. It claims to be compatible with Control.Monad.Trans which... I guess means mtl?

At any rate, I'd suggest the following decision algorithm:

  • Do you need standard monads for a new project? Use transformers & co., help us lay mtl to rest.
  • Are you already using mtl in a large project? transformers isn't completely compatible, but no one will kill you for not switching.
  • Does one of the other packages provide unusual functionality that you need? Might as well use it rather than rolling your own.
  • Still unsatisfied? Throw them all out, download category-extras, and solve all the world's problems with a page and a half of incomprehensible abstract nonsense breathtakingly generic code.

For the moment? You should probably use mtl. What is happening is that the transformers library is being factored out of the MTL in a fashion that monads-fd and monads-tf can co-exist peacefully, but at last check that was not yet the case.

When that happens you'll be able to import monads-fd and transformers and get (almost) the same interface, with the exception that State, etc. will be an alias for StateT.

So I'd write to mtl, but not rely on the fact that State, Reader, etc. are currently data as they will be replaced with types.

MonadLib is another alternative that Iavor has been working on, which can be safely used because it doesn't share any module names with the others, but which has a fairly different usage pattern.

The factoring out Edward Kmett mentions in his answer was completed in late 2010. Its end result was monads-fd, built upon transformers, becoming version 2 of mtl. As a consequence of the ubiquitousness of mtl, monads-tf never really caught on. As of early 2017, mtl and transformers are the only monad transformer libraries that see widespread usage.