感谢 Willem Van Onsem 的精彩回答。
让我们从ghc的类型推断系统的角度来理解zipWith id。
首先,考虑zipWith的类型
Prelude> :info zipWith
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
-- Defined in ‘GHC.List’
zipWith 的第一个参数是一个函数,它接受一个带有两个参数的函数。
(a -> b -> c)也可以改写为a -> (b -> c)
现在考虑zipWith id。 id 的类型来自 a -> a
我们已将id 放在一个必须包含两个参数的函数的位置。
因此,类型推断会使 (a -> b -> c) 看起来像 a -> (b -> c)(注意 a -> (b -> c) 接受一个参数 a 并给出 b -> c 即单个参数函数。)
但是,只有当a 是 (b -> c) 时,才能将 a -> (b -> c) 设为恒等函数。
当a 为 (b -> c) 时,函数a -> b -> c 变为 ((b -> c) -> (b -> c))
因此,类型推断系统会将a 推断为(b -> c),结果输出将是[a] -> [b] -> [c] 将a 替换为b -> c。
将a 替换为 (b -> c)。
使 (a -> b -> c) 看起来像 id。 (a -> b -> c) 可以通过上面的替换看起来像id。
((b -> c) -> b -> c) 也可以写成 ((b -> c) -> (b -> c)) 这是id :: x -> x 其中x 是 ( b -> c)
zipWith :: ((b -> c) -> b -> c) -> [b -> c] -> [b] -> [c]
所以最后我们得到[b -> c] -> [b] -> [c]的输出