显然必须有系统的方式,否则Haskell编译器无法进行类型推断。
我们自己可以这样做的一种方法是逐步插入类型:
我们有以下几种:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
map :: (a' -> b') -> [a'] -> [b']
foldr :: Foldable t => (a'' -> b'' -> b'') -> b'' -> t a'' -> b''
请注意,您必须为出现在不同签名中的类型选择不同的名称才能解决此问题。
1.将map 提供给(.)
如果我们提供一个泛型函数f 到(.),我们会得到以下类型:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(.) f :: (a -> b) -> (a -> c)
f :: (b -> c)
选择f为map:
map :: (a' -> b') -> [a'] -> [b']
等于
map :: (a' -> b') -> ([a'] -> [b'])
由于f 的类型为(b -> c),我们可以得出结论:
b :: (a' -> b')
c :: ([a'] -> [b'])
插入我们推断的类型:
(.) f :: (a -> b) -> (a -> c)
(.) map :: (a -> (a' -> b')) -> (a -> ([a'] -> [b']))
我们可以去掉一些括号:
(.) map :: (a -> (a' -> b')) -> a -> ([a'] -> [b'])
(.) map :: (a -> (a' -> b')) -> a -> [a'] -> [b']
(.) map :: (a -> a' -> b') -> a -> [a'] -> [b']
2。将foldr 提供给(.) map
再次从提供泛型函数g开始:
(.) map :: (a -> a' -> b') -> a -> [a'] -> [b']
(.) map g :: a -> [a'] -> [b']
g :: (a -> a' -> b')
选择g为foldr:
foldr :: Foldable t => (a'' -> b'' -> b'') -> b'' -> t a'' -> b''
等于
foldr :: Foldable t => (a'' -> b'' -> b'') -> b'' -> (t a'' -> b'')
由于g 的类型为(a -> a' -> b'),我们可以得出结论:
a :: (a'' -> b'' -> b'')
a' :: b''
b' :: Foldable t => t a'' -> b''
插入我们推断的类型:
(.) map foldr :: a -> [a'] -> [b']
(.) map foldr :: Foldable t => (a'' -> b'' -> b'') -> [b''] -> [t a'' -> b'']
当向 ghci 询问类型时,我们得到的类型相同:
> :t ((.) map foldr)
((.) map foldr) :: Foldable t => (a1 -> a2 -> a2) -> [a2] -> [t a1 -> a2]