我正在实现一个函数 combine :: [[a]] -> [[b]] -> (a -> b -> c) -> [[c]]
,它给出了两个二维列表,将给定的函数 f :: a -> b -> c
应用于二维列表的条目。换句话说:
[[a, b, c], [[r, s, t], [[f a r, f b s, f c t],
combine [d, e, g], [u, v, w], f = [f d u, f e v, f g w],
[h, i, j]] [x, y, z]] [f h x, f i y, f j z]]
现在我怀疑
combine = zipWith . zipWith
,因为我已经尝试过了,它给了我预期的结果,例如(zipWith . zipWith) (\x y -> x+y) [[1,2,3],[4,5,6]] [[7,8,9],[10,11,12]]
给出了预期的结果
[[8,10,12],[14,16,18]]
,但我不明白为什么会这样,因为我不明白 zipWith . zipWith
的类型是如何变成 (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
的。这里的
(.)
还在进行通常的函数组合吗?如果是这样,您能解释一下这如何适用于 zipWith
吗? 最佳答案
要推断 zipWith . zipWith
等表达式的类型,您可以通过以下方式在头脑中模拟统一。
第一个 zipWith
的类型为 (a -> b -> c) -> ([a] -> [b] -> [c])
,第二个 (s -> t -> u) -> ([s] -> [t] -> [u])
和 (.)
的类型为 (m -> n) -> (o -> m) -> (o -> n)
。
要对其进行类型检查,您需要:
m
= (a -> b -> c)
n
= ([a] -> [b] -> [c])
o
= (s -> t -> u)
m
= ([s] -> [t] -> [u])
=> a
= [s]
, b
= [t]
, c
= [u]
因为第一个约束 然后返回的类型是
o -> n
,它是来自约束的 (s -> t -> u) -> ([a] -> [b] -> [c])
并且更进一步 (s -> t -> u) -> ([[s]] -> [[t]] -> [[u]])
。关于haskell - 为什么 zipWith.zipWith 工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46619990/