この関数を定義して、3 つのペアのリストを再グループ化しようとしていました。
{-# 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
ですが、この、つまり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
あらゆるタイプを受け入れることができるはずです。私が理解していないのは、特定のコンテキスト内で一度使用され、定義が残りのコンテキストで「固定」されるかどうかです。
「chips」と「rice」を Ints に置き換えても、コンパイラはまだ文句を言うので、そうではないようです。そのため、何か間違っていると推測していると思います (もちろん、mapAndZip3
この後者の場合の型注釈を削除すると、署名が に簡略化されるため、すべて mapAndZip3 :: (a -> t) -> [a] -> [a] -> [a] -> [(t, t, t)]
がうまくいきますが、これは私が望むものではありません)。
私もこの質問を見つけましたが、これが同じ問題であるかどうかは実際にはわかりません。適用しようとしている関数は実際には異なる型を返す関数ではないid
ためです。fst
snd
(a -> b)