haskell - (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
列表。我也不明白为什么它只适用于一个功能,因为两者都需要一个。
有人可以解释一下它是如何工作的吗?
解决方案
首先,让我们为函数中的类型使用不同的字母。这样我们就不会糊涂了。
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])
所以我们可以在d
和f
的定义中代替(.)
and 得到
(c -> Bool) -> [[c]] -> [[c]]
这就是 GHCi 告诉我们的。
这个函数实际上所做的是将过滤器应用于每个子列表;采用的函数参数map
是过滤器。所以在 GHCi 中,
Prelude> import Data.Char
Prelude Data.Char> (map.filter) isDigit ["foo123", "456bar"]
["123","456"]
推荐阅读
- python - Django 2.1:是否可以在电子邮件中包含 Ngrok 的域而不是本地主机的域?
- node.js - 函数不会等到 Promise 被解决
- c# - 为什么 AddExplosionForce 在我的代码中不起作用?
- dc.js - 交叉过滤堆叠条形图否定值
- php - 为数据表减去 foreach 循环中的两个总和
- php - 将 PHP 用于 webhook 时,如何获得短提交 ID 和长提交 ID?
- next.js - Next.js 静态/导出站点中的启动时初始化
- python - Python:使用关键字在行之间搜索文本
- haskell - 如何找到列表中两个元素之间的距离?
- android - 当我使用 ViewModel.Factory 时,出现`Kodein No binding found for bind
()` 错误