我想知道我们不能对类型类进行抽象是否有更深层次的原因(或者我们可以吗?)。
例如,当我们有
fzip :: (forall a.[a] -> [a]) -> [b] -> [c] -> [(b,c)]
fzip f xs ys = zip (f xs) (f ys)
那么我们可以说
fzip (drop 42) [1..100] ['a'..'z']
fzip reverse [1..100] ['a'..'z']
等等。但我们不能
fzip (map succ) [1..100] ['a'..'z']
我们可以用以下方法修复:
ezip :: (Enum b, Enum c) => (forall a.Enum a => [a] -> [a]) -> [b] -> [c] -> [(b,c)]
ezip f xs ys = zip (f xs) (f ys)
同样我们可以修复
fzip (map (5*)) [1..100] [1.5, 2.3, 4.7]
with
nzip :: (Num b, Num c) => (forall a.Num a => [a] -> [a]) -> [b] -> [c] -> [(b,c)]
nzip f xs ys = zip (f xs) (f ys)
但我们不能包容,这不是很尴尬吗?ezip
and nzip
类似的东西:
gzip :: (g b, g c) => (forall a. g a => [a] -> [a]) -> [b] -> [c] -> [(b,c)]
尽管代码是完全相同的,但直到类的名称?
或者我们能以某种方式吗?
有趣的是,当实例只是包含函数的记录时,这很容易实现。