在Haskell中编写嵌套的Monad [英] Compose nested Monads in Haskell

查看:85
本文介绍了在Haskell中编写嵌套的Monad的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法可以为嵌套的monad实现绑定?我想要的是以下签名:

Is there a way to implement bind for nested monads? What I want is the following signature:

(>>>=) :: (Monad m, Monad n) => m (n a) -> (a -> m (n b)) -> m (n b)

看起来这应该是一件微不足道的任务,但是我莫名其妙地无法解决这个问题.在我的程序中,我将这种模式用于monad的几种不同组合,并且对于每种组合,我都可以实现它.但是对于一般情况,我只是不理解.

It looks like it should be a trivial task, but I somehow just can't wrap my head around it. In my program, I use this pattern for several different combinations of monads and for each combination, I can implement it. But for the general case, I just don't understand it.

在一般情况下,这似乎是不可能的.但是在某些特殊情况下当然是可能的.例如.如果内部的Monad是Maybe.由于我想使用的所有Monad都有可能,所以对我来说,附加约束似乎很好.所以我稍微改变了这个问题:

It seems that it is not possible in the general case. But it is certainly possible in some special cases. E.g. if the inner Monad is a Maybe. Since it IS possible for all the Monads I want to use, having additional constraints seems fine for me. So I change the question a bit:

我需要对n进行哪些附加约束,以便可能进行以下操作?

What additional constraints do I need on n such that the following is possible?

(>>>=) :: (Monad m, Monad n, ?? n) => m (n a) -> (a -> m (n b)) -> m (n b)

推荐答案

扩展注释:如链接 问题显示,必须具有某些功能n (m a) -> m (n a)甚至有机会将作品变成单声道.

Expanding on the comments: As the linked questions show, it is necessary to have some function n (m a) -> m (n a) to even have a chance to make the composition a monad.

如果您的内部monad是Traversable,则sequence提供了这样的功能,并且以下内容将具有正确的 type :

If your inner monad is a Traversable, then sequence provides such a function, and the following will have the right type:

(>>>=) :: (Monad m, Monad n, Traversable n) => m (n a) -> (a -> m (n b)) -> m (n b)
m >>>= k = do
    a <- m
    b <- sequence (map k a)
    return (join b)

实际上,有几个知名的转换器是与之等效的简单新型包装器(尽管大多数情况下都是通过模式匹配来定义内容,而不是使用内部monad的MonadTraversable实例):

Several well-known transformers are in fact simple newtype wrappers over something equivalent to this (although mostly defining things with pattern matching instead of literally using the inner monads' Monad and Traversable instances):

  • MaybeT based on Maybe
  • ExceptT based on Either
  • WriterT based on (,) ((,) doesn't normally have its Monad instance defined, and WriterT is using the wrong tuple order to make use of it if it had - but in spirit it could have).
  • ListT based on []. Oh, whoops...

最后一个实际上是臭名昭著的,因为除非解除的单子是可交换的",否则不是是单子-否则,单子法则应相等的表达式会产生不同的效果顺序.我的直觉是,这本质上是由于列表能够包含多个值,而不同于其他可靠的示例.

The last one is in fact notorious for not being a monad unless the lifted monad is "commutative" - otherwise, expressions that should be equal by the monad laws can give different order of effects. My hunch is that this comes essentially from lists being able to contain more than one value, unlike the other, reliably working examples.

因此,尽管可以正确地键入上述定义,但仍可能违反单子法则.

So, although the above definition will be correctly typed, it can still break the monad laws.

还有一个事后思考,另一个转换器就是这样一个嵌套的monad,但以完全不同的方式:ReaderT,基于将(->)用作 outer monad.

Also as an afterthought, one other transformer is such a nested monad, but in a completely different way: ReaderT, based on using (->) as the outer monad.

这篇关于在Haskell中编写嵌套的Monad的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆