首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么Haskell假定返回的monad类型与作为参数传递的类型相同?

为什么Haskell假定返回的monad类型与作为参数传递的类型相同?
EN

Stack Overflow用户
提问于 2019-03-26 00:06:37
回答 1查看 148关注 0票数 5

为什么要编译这段代码?

代码语言:javascript
运行
复制
--sequence_mine :: Monad m => [m a] -> m [a]
sequence_mine [] = return []
sequence_mine (elt:l) = do
  e <- elt
  sl <- sequence l
  return (e:sl)

注意:我有意注释掉了这里的类型声明。但是,即使没有类型声明,代码仍然可以编译,并且看起来像预期的那样工作--这让我感到惊讶。

据我所知,这一行应该出现歧义:

代码语言:javascript
运行
复制
return (e:sl)

原因是Haskell不应该知道我们返回的是哪种类型的monad。为什么它必须是我们正在接受的同一类型?

来澄清更多。据我所知,如果我不明确地将类型声明类似于我注释掉的类型声明,Haskell应该推断该函数具有如下类型:

代码语言:javascript
运行
复制
sequence_mine :: (Monad m1, Monad m2) => [m1 a] -> m2 [a]

除非我明确地将m1m2统一起来,将它们都称为m,否则Haskell没有理由相信它们指的是同一类型!我想是的。

然而,事实并非如此。这里我漏掉了什么?

EN

Stack Overflow用户

回答已采纳

发布于 2019-03-26 00:15:55

好了,让我们来看看do块的目的是什么:

代码语言:javascript
运行
复制
sequence_mine (elt:l) = elt >>= \e -> (sequence l) >>= \sl -> return (e:sl)

回想一下,“绑定”操作符>>=具有类型签名(Monad m) => m a -> (a -> m b) -> m b。请注意,这里的单体m虽然是任意的,但对于参数和结果类型必须是相同的。

因此,如果elt具有类型m a,则很容易看出return (e:sl) --即整个表达式的输出类型--必须具有类型m [a],用于相同的monad m

换句话说,每个do块只在固定monad的上下文中工作。

票数 7
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55341953

复制
相关文章

相似问题

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