对于monad,可以通过bind来定义join吗?

在Haskell中,monads是根据函数return和bind定义的,其中return的类型a -> ma ,bind的类型为ma -> (a -> mb) -> mb 。 之前已经指出单子也可以用返回和连接来定义,其中连接是类型为m (ma) -> ma的函数。 绑定可以根据连接来定义,但是可能相反吗? 可以根据绑定来定义连接吗?

如果没有加入,我不知道如果我以某种方式获得了“两次包裹”一元值, m (ma) - 没有任何函子或monad操作“删除任何图层”,我会做什么。 如果这是不可能的,为什么Haskell和其他monad实现在绑定方面定义它们? 它似乎严格地比基于连接的定义更有用。


有可能的:

join :: Monad m => m (m a) -> m a
join m = (m >>= id)

注意>>=的棘手实例:

(>>=) :: m b -> (b -> m c) -> m c
-- choosing b ~ m a , c ~ a
(>>=) :: m (m a) -> (m a -> m a) -> m a

所以我们可以正确选择id作为第二个参数。


是的,这很简单:

join m = m >>= id

绑定( >>= )确实“删除图层”:

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

直觉告诉我“得到了一些a出去了的的ma ”,并于随后把a -> mb功能,然后产生一个mb的结果。

人们通常会说它需要函数参数才能以m重新计算输出,但事实并非如此。 它要求函数的输出是以m为单位的东西,但是包装的来源并不重要。

在实现join的情况下,我们从“双重包装”开始: m (ma) 。 我们可以将它插入bind的签名,并立即找出绑定“双重包装”值时可以使用的函数的类型:

m (m a) -> (m a -> m b) -> m b

现在,用于绑定的函数将接收一个已经包含在m 。 所以我们不必“重新包装”任何东西; 如果我们未经修改就返回它,它已经是输出的正确类型。 有效地,这是“删除了一层包装” - 这适用于任何层,但最后一层。

所以这告诉我们我们只需要绑定id

join = (>>= id)
链接地址: http://www.djcxy.com/p/33223.html

上一篇: With monads, can join be defined in terms of bind?

下一篇: Can I automatically implement classes?