在Haskell中,monads是根据函数返回和绑定来定义的,其中返回类型为a -> m a,而bind具有m a -> (a -> m b) -> m b类型。在此之前已经指出过monads也可以定义为返回和连接。,其中join是一个具有m (m a) -> m a类型的函数。绑定可以用联接来定义,但反向可能吗?可以用绑定来定义联接吗?
如果没有join,我不知道如果我以某种方式获得了一个“两次包装”的一元值,m (m a) --可以说,函子或monad操作中没有一个“移除任何层”,我不知道我会怎么做。如果这是不可能的,为什么Haskell和许多其他的monad实现要用bind来定义它们?与基于连接的定义相比,它似乎没有那么有用。
发布于 2015-12-21 14:46:02
有可能:
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作为第二个参数。
发布于 2015-12-21 14:44:53
是的,很简单:
join m = m >>= id发布于 2015-12-21 22:28:24
Bind (>>=)实际上是“删除一个层”:
(>>=) :: Monad m => m a -> (a -> m b) -> m b直观地说,它“从a中获取一些m a",然后输入到a -> m b函数,然后根据结果生成一个m b。
人们通常说,它需要函数参数才能在m中再次结束它的输出,但事实并非如此。它要求函数的输出必须封装在m中,但包装来自何处并不重要。
在实现join的情况下,我们从“双包装”开始:m (m a)。我们可以将其插入绑定的签名中,并立即确定绑定“双包装”值时可以使用的函数类型:
m (m a) -> (m a -> m b) -> m b现在,这里使用的绑定函数将接收一个已经包装在m中的值。因此,我们不需要“重新包装”任何东西;如果我们不修改地返回它,那么它已经是输出的正确类型。这实际上是“删除了一层包装”--这适用于除最后一层之外的任何一层。
所以这告诉我们,我们只需要绑定到id
join = (>>= id)https://stackoverflow.com/questions/34398239
复制相似问题