Has*_*ant 7 monads haskell monad-transformers
比方说,我们要使用ReaderT [(a,b)]过Maybe单子,然后我们想要做的列表中查找.
现在,一个简单但不太常见的方法是:
第一种可能性
find a = ReaderT (lookup a)
Run Code Online (Sandbox Code Playgroud)
然而,看起来这似乎是关于ReaderT变压器如何工作的一些重要的事情.查看Control.Monad.Reader的源代码,很明显这很好用.但我没有阅读任何支持此文件的文件.但是我们也可以这样写:
第二种可能性
find a = do y <- ask
lift (lookup a y)
Run Code Online (Sandbox Code Playgroud)
类似的想法保持包装MaybeT,StateT,State和Reader.通常我会写第一个例子,但大部分时间都很明显如何像第二个例子那样编写它,你甚至可以说它更具可读性.所以我的问题是:如果第一个例子的代码被认为是坏的吗?
我认为第一种方式的最大问题是:
如果mtl作者(或你使用的任何变换器库)决定停止导出ReaderT的数据构造函数,那么它将停止工作.这发生在从mtl 1到mtl 2的版本颠簸中的State monad并且它非常烦人.虽然,
ask是Reader的官方api的一部分,你应该计划坚持下去.
另一方面,我不认为第一种方式是错误的.
mtl库的当前版本(基于Transformersreader :: (r -> a) -> Reader r a库)在使用简单 monad 时导出正是用于此目的的函数Reader。所以我们看到库的设计确实考虑到了这种用法。由于没有提供这样的函数ReaderT,我们可以有信心地说,官方支持的方法ReaderT是直接使用构造函数。
readerT :: Monad m => (r -> a) -> ReaderT r m a如果您说应该将类似的内容添加到库中,我会同意您的观点。这对于一致性和允许有一天在不破坏任何人的代码的情况下更改内部表示的可能性都是有好处的。
但就目前而言,“第一种可能性”是要走的路。