首页 > 解决方案 > 为什么带有`join`的函数组合可以改变函数输入?

问题描述

我最近开始学习 Haskell,我试图做以下函数组合 ( join . mapM),但是从这个函数中得到了一些我不理解的奇怪类型。我认为要么 GHC 会假设t == mmapM类型和输出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像我一样做出假设,我有一半的预期,它应该因为类型不匹配而出错,而不是更改输入函数类型,对吗?这里发生了什么?

标签: haskellmonadsfunction-composition

解决方案


首先,您专注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

推荐阅读