首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对于单子,可以用绑定来定义联接吗?

对于单子,可以用绑定来定义联接吗?
EN

Stack Overflow用户
提问于 2015-12-21 14:41:15
回答 5查看 1.9K关注 0票数 14

在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来定义它们?与基于连接的定义相比,它似乎没有那么有用。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2015-12-21 14:46:02

有可能:

代码语言:javascript
复制
join :: Monad m => m (m a) -> m a
join m = (m >>= id)

注意>>=的复杂实例化

代码语言:javascript
复制
(>>=) :: m b -> (b -> m c) -> m c
-- choosing b ~ m a , c ~ a
(>>=) :: m (m a) -> (m a -> m a) -> m a

因此,我们可以正确地选择id作为第二个参数。

票数 17
EN

Stack Overflow用户

发布于 2015-12-21 14:44:53

是的,很简单:

代码语言:javascript
复制
join m = m >>= id
票数 7
EN

Stack Overflow用户

发布于 2015-12-21 22:28:24

Bind (>>=)实际上是“删除一个层”:

代码语言:javascript
复制
(>>=) :: Monad m => m a -> (a -> m b) -> m b

直观地说,它“从a中获取一些m a",然后输入到a -> m b函数,然后根据结果生成一个m b

人们通常说,它需要函数参数才能在m中再次结束它的输出,但事实并非如此。它要求函数的输出必须封装在m中,但包装来自何处并不重要。

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

代码语言:javascript
复制
m (m a) -> (m a -> m b) -> m b

现在,这里使用的绑定函数将接收一个已经包装在m中的值。因此,我们不需要“重新包装”任何东西;如果我们不修改地返回它,那么它已经是输出的正确类型。这实际上是“删除了一层包装”--这适用于除最后一层之外的任何一层。

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

代码语言:javascript
复制
join = (>>= id)
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34398239

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档