首页 > 解决方案 > (map .filter)的通用类型

问题描述

我不明白为什么map . filter泛型类型是map . filter :: (a -> Bool) -> [[a]] -> [[a]].

我知道 map 和 filter 类型是map :: (a -> b) -> [a] -> [b]and filter :: (a -> Bool) -> [a] -> [a]。还有(.) :: (b -> c) -> (a -> b) -> a -> c.

所以我的猜测是a = (a -> Bool) -> [a]b = [a]并且由于 filter 的输出不是函数,我认为这map . filter将返回一个期望 function 的函数(a -> b)

我不明白为什么该类型是 列表的列表a,因为既map没有列表也没有filter列表。我也不明白为什么它只适用于一个功能,因为两者都需要一个。

有人可以解释一下它是如何工作的吗?

标签: haskellfiltertypestype-inferencemap-function

解决方案


首先,让我们为函数中的类型使用不同的字母。这样我们就不会糊涂了。

map :: (a -> b) -> [a] -> [b]
filter :: (c -> Bool) -> [c] -> [c]
(.) :: (e -> f) -> (d -> e) -> d -> f

所以现在我们考虑map . filter。进行替换,我们得到以下结果(~用于类型相等):

d ~ (c -> Bool)
e ~ ([c] -> [c])   -- Result of 'filter'
e ~ (a -> b)       -- Argument of 'map'
f ~ ([a] -> [b])

请注意我们如何获得两种类型的e. 通过替换,

a ~ b ~ [c]

所以因此

f ~ ([[c]] -> [[c])

所以我们可以在df的定义中代替(.)and 得到

(c -> Bool) -> [[c]] -> [[c]]

这就是 GHCi 告诉我们的。

这个函数实际上所做的是将过滤器应用于每个子列表;采用的函数参数map是过滤器。所以在 GHCi 中,

Prelude> import Data.Char
Prelude Data.Char> (map.filter) isDigit ["foo123", "456bar"]
["123","456"]

推荐阅读