2

我试图推导出的类型(.) (foldr(++)) (map (:))

我首先推导类型foldr (++)

foldr :: (a1 -> b1 -> b1) -> b1 -> [a1] -> b1
(++)  :: [a2] -> [a2] -> [a2]

a1 ~ [a2]
b1 ~ [a2]
b1 ~ [a2]

所以

foldr (++) :: [a2] -> [[a2]] -> [a2] ~ [a] -> [[a]] -> [a]

然后我推导出类型map (:)

map :: (a1 -> b1) -> [a1] -> [b1]
(:) :: a2 -> [a2] -> [a2]

a1 ~ a2
b1 ~ [a2] -> [a2]

所以

map (:) :: [a2] -> [[a2] -> [a2]] ~ [a] -> [[a] -> [a]]

最后的类型(.) (foldr(++)) (map (:))

(.) :: (b1 -> c1) -> (a1 -> b1) -> a1 -> c1
map (:) :: [a2] -> [[a2] -> [a2]]
foldr (++) :: [a3] -> [[a3]] -> [a3]

b1 ~ [a2]
c1 ~ [[a2] -> [a2]]
a1 ~ [a3]
b1 ~ [[a3]] -> [a3]

所以我得到

(.) (foldr(++)) (map (:)) :: a1 -> c1 ~ [a3] ->  [[a2] -> [a2]]

但是如果我问 GHCi:t (.) (foldr(++)) (map (:))我得到(.) (foldr(++)) (map (:)) :: [a] -> [[[a] -> [a]]] -> [[a] -> [a]]

这与我的结果不同,有什么帮助可以得出相同的结果吗?

谢谢,
塞巴斯蒂安。

4

2 回答 2

9

在最后一步中,您混合了参数 oder。您b1 -> c1与 的类型统一map (:),但您应该将其与 的类型统一foldr (++)

更一般地说,您可能想学习如何自己调试这些复杂的计算。最好在最后进行完整性检查(在这种情况下,通过使用 ghci 检查结果)。如果健全性检查不起作用,下一步可以说或写下每个步骤是什么以及为什么这样做。在这种情况下,您会说“然后我b1 -> c1与类型统一,map (:)因为 ...”,您会在那里找到错误,因为没有理由这样做。

也许橡皮鸭调试对你有用,你向橡皮鸭解释你的代码,通过解释,你会看到代码有什么问题。.

于 2014-05-02T20:30:40.477 回答
3

我不太确定,但我认为您b1错过f . ggf. 通过从该事实开始,然后替换输入和输出,可以更容易地推断组合的类型:

map (:)              :: [a] -> [[a] -> [a]]
foldr (++)           ::        [b         ] -> [[b         ]] -> [b         ]

[b] ~ [[a] -> [a]]
 b  ~  [a] -> [a]

foldr (++) . map (:) :: [a]                 -> [[b         ]] -> [b         ]
                      ~ [a]                 -> [[[a] -> [a]]] -> [[a] -> [a]]
于 2014-05-02T20:30:07.543 回答