手动派生`zipWith的类型。 uncurry`

时间:2014-05-03 00:43:51

标签: haskell types ghci unification

我正在尝试派生zipWith . uncurry

的类型

zipWith . uncurry = (.) zipWith uncurry - 连接为函数

(.) :: (b1 -> c1) -> (a1 -> b1) -> a1 -> c1
zipWith :: (a2 -> b2 -> c2) -> [a2] -> [b2] -> [c2]
uncurry :: (a3 -> b3 -> c3) -> (a3, b3) -> c3

b1 ~ (a2 -> b2 -> c2)
c1 ~ [a2] -> [b2] -> [c2]
a1 ~ (a3 -> b3 -> c3)
b1 ~ (a3, b3) -> c3

a1替换为(a3 -> b3 -> c3),将c1替换为[a2] -> [b2] -> [c2]我得到:

(.) zipWith uncurry :: a1 -> c1 ~ (a3 -> b3 -> c3) -> [a2] -> [b2] -> [c2]

如果我查询:t zipWith . uncurry的GHCi,我会得到:(a -> b1 -> b -> c) -> [(a, b1)] -> [b] -> [c]

我认为关键在于b1 ~ (a2 -> b2 -> c2) ~ (a3, b3) -> c3,但我没有意识到如何将我的结果与预期相匹配。

任何帮助?

谢谢,
安。

1 个答案:

答案 0 :(得分:4)

如果我们从

开始
(.) :: (b -> c) -> (a -> b) -> (a -> c)
zipWith :: (x -> y -> z) -> [x] -> [y] -> [z]
uncurry :: (u -> v -> w) -> (u, v) -> w

然后我们将zipWith的类型与(b -> c)uncurry的类型与(a -> b)匹配:

b             -> c
(x -> y -> z) -> ([x] -> [y] -> [z])

a             -> b
(u -> v -> w) -> ((u, v) -> w)

然后我们必须将b条款等同于

b ~ x      -> (y -> z)
b ~ (u, v) -> w

所以w ~ (y -> z)x ~ (u, v)。我们目前已确定的表格:

a ~ u -> v -> w
b ~ x -> y -> z
c ~ [x] -> [y] -> [z]
x ~ (u, v)
w ~ y -> z

因此,我们可以将xw替换为:

a ~ u -> v -> (y -> z)
b ~ (u, v) -> y -> z
c -> [(u, v)] -> [y] -> [z]

我们现在可以完成zipWith . uncurry的类型:

(u -> v -> y -> z) -> ([(u, v)] -> [y] -> [z])

与GHCi的答案一致。

这些技巧只是排列箭头,然后直接替换,直到你不能再减少它为止。