haskell - 为什么带有`join`的函数组合可以改变函数输入?
问题描述
我最近开始学习 Haskell,我试图做以下函数组合 ( join . mapM
),但是从这个函数中得到了一些我不理解的奇怪类型。我认为要么 GHC 会假设t == m
在mapM
类型和输出mapM
中将成为m (m b)
可连接的或不能连接的,这会由于类型不匹配而出错。相反,发生了以下情况:
mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
join :: Monad m => m (m a) -> m a
join . mapM :: Traversable t => (a -> t a -> b) -> t a -> t b
我不明白这怎么可能。我理解它的方式,函数组合应该使用第一个(或第二个,取决于你如何看待它)函数的输入和第二个函数的输出。但是这里预期的输入函数mapM
从一元函数变为二元函数,我不知道为什么。即使 GHC 不能t == m
像我一样做出假设,我有一半的预期,它应该因为类型不匹配而出错,而不是更改输入函数类型,对吗?这里发生了什么?
解决方案
首先,您专注mapM
于:
mapM' :: Traversable t => (a -> x -> b) -> t a -> x -> t b
(因为(->) x
是一个单子)
然后,您将其进一步专门用于:
mapM'' :: Traversable t => (a -> t a -> b) -> t a -> t a -> t b
(我们只是在解决这个x
问题t a
)
最后,我们join
适当地专门化:
join' :: (x -> x -> r) -> x -> r
(再次,(->) x
是一个单子)
并希望它变得更加明显,为什么组合join' . mapM''
是
join' . mapM'' :: Traversable t => (a -> t a -> b) -> t a -> t b
推荐阅读
- sql - SSDT 包 (.dtsx) 上数据流中的错误转换日期 nvarchar 到 datetime
- dart - await for(var msg in receivePort) 和 receivePort.listen() 有什么区别?
- excel - 按顺序排列工作表
- arrays - Vuex中突变数组的棘手问题,如何解决?
- javascript - 我必须从 Controller 访问表 tr 以获取高亮行
- odoo - 更改树视图 odoo 发票中的总金额
- javascript - 添加到现有网页的 React 不会渲染来自多个文件的组件
- android - Android rxjava 改造链调用不起作用
- laravel - ErrorException (E_ERROR) 未定义变量:userdata
- mysql - 如何将表 2 中的新行插入到表 1 中比较 ID?