的对我试图定义此功能重新组合对三个列表:RankNTypes:应用相同的功能,不同类型的
{-# LANGUAGE RankNTypes #-}
mapAndZip3 :: (forall x. x -> f x) -> [a] -> [b] -> [c]
-> [(f a, f b, f c)]
mapAndZip3 f la lb lc = zipWith3 (\a b c -> (f a, f b, f c)) la lb lc
main = do
let x = mapAndZip3 (fst) [(1,"fruit"), (2,"martini")]
[("chips","fish"),("rice","steak")]
[(5,"cake"),(4,"pudding")]
print x -- was expecting [(1,"chips",5), (2,"rice",4)]
起初我并没有包括RankNTypes
或forall
,但随后在录入this后,即liftTup
的定义,我认为它应该够了。
但显然,它不是,因为我还得到一个错误:
mapAndZip3.hs:8:25:
Couldn't match type `x' with `(f0 x, b0)'
`x' is a rigid type variable bound by
a type expected by the context: x -> f0 x at mapAndZip3.hs:8:13
Expected type: x -> f0 x
Actual type: (f0 x, b0) -> f0 x
In the first argument of `mapAndZip3', namely `(fst)'
我明明有forall
关键字的了解有限,但是从我的理解是应该在这种情况下,允许为f
接受任何类型。我不明白的是:一旦在给定的背景下使用过一次,定义是否会在剩下的环境中“固定”?因为如果我用Ints替换“芯片”和“米”,编译器仍然抱怨,所以我想我错了(当然,如果我删除了类型注释mapAndZip3
在后一种情况下,因为签名被简化为mapAndZip3 :: (a -> t) -> [a] -> [a] -> [a] -> [(t, t, t)]
,所有东西都可以使用,但这不是我想要的)。
我也发现了这个question,却无法真正使这是否是同样的问题或没有,因为我尝试应用功能不id
,但fst
或snd
,实际上返回不同类型(a -> b)
功能。
谢谢!我真的很难选择一个正确的答案,因为实际上这两个答案都是不可能的。尽管我非常喜欢Daniel Fischer的回答,因为起初最容易理解,左边的回答确实给了我一些额外的背景。欢呼都! – jcristovao