6

この関数を定義して、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ためです。fstsnd(a -> b)

4

2 に答える 2

8

問題はfst、必要なタイプがないことです

(forall x. x -> f x)

のタイプfst

fst :: (a, b) -> a

でありa、 の形式ではありませんf (a,b)。、、などの型コンストラクターでfインスタンス化する必要がある変数があります。のような「型関数」を表すことはできません。型コンストラクターでなければなりません。[]MaybeEither BoolfΛ (a,b) -> a

必要なタイプの関数を提供すると機能します (申し訳ありませんが、ばかげた例です):

{-# 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

fst0 x = (True,x)

main = do
    let x = mapAndZip3 (fst0) [(1 :: Int,"fruit"), (2,"martini")]
                             [("chips","fish"),("rice","steak")]
                             [(5 :: Int,"cake"),(4,"pudding")]
    print x

ここfst0には typea -> ((,) Bool) aがあり、フォームはx -> f xです。

于 2013-06-05T10:39:37.807 に答える