数週間前、私はWriting an interpreter using foldを読んでいます。私はこの方法を私が取り組んでいるプロジェクトに適用しようとしましたが、GADTのためにエラーがありました。ここで同じ問題を生成するおもちゃのコードです。GADTで折りたたみ通訳を使用する
{-# LANGUAGE GADTs, KindSignatures #-}
data Expr :: * -> * where
Val :: n -> Expr n
Plus :: Expr n -> Expr n -> Expr n
data Alg :: * -> * where
Alg :: (n -> a)
-> (a -> a -> a)
-> Alg a
fold :: Alg a -> Expr n -> a
fold [email protected](Alg val _) (Val n) = val n
fold [email protected](Alg _ plus) (Plus n1 n2) = plus (fold alg n1) (fold alg n2)
ここにエラーメッセージがあります。
/home/mossid/Code/Temforai/src/Temforai/Example.hs:16:36: error:
• Couldn't match expected type ‘n1’ with actual type ‘n’
‘n’ is a rigid type variable bound by
the type signature for:
fold :: forall a n. Alg a -> Expr n -> a
at /home/mossid/Code/Temforai/src/Temforai/Example.hs:15:9
‘n1’ is a rigid type variable bound by
a pattern with constructor:
Alg :: forall a n. (n -> a) -> (a -> a -> a) -> Alg a,
in an equation for ‘fold’
at /home/mossid/Code/Temforai/src/Temforai/Example.hs:16:11
• In the first argument of ‘val’, namely ‘n’
In the expression: val n
In an equation for ‘fold’: fold [email protected](Alg val _) (Val n) = val n
• Relevant bindings include
n :: n
(bound at /home/mossid/Code/Temforai/src/Temforai/Example.hs:16:27)
val :: n1 -> a
(bound at /home/mossid/Code/Temforai/src/Temforai/Example.hs:16:15)
fold :: Alg a -> Expr n -> a
(bound at /home/mossid/Code/Temforai/src/Temforai/Example.hs:16:1)
私は、コンパイラがn
とn1
が同じ種類であることを推測することはできませんので、答えはデータ型のシグネチャに内部変数を持ち上げるかもしれないと思います。ただし、この例のように、元のコードでは使用できません。元のコードはExpr
にforall-quantified型変数を持ち、型シグネチャは特定の情報を処理する必要があります。
+ここでは、あなたがAlg
型コンストラクタにパラメータとして、それを公開することができ、Alg
内部n
が正しいものであることを確認するには、元のコード
data Form :: * -> * where
Var :: Form s
Prim :: (Sat s r) => Pred s -> Marker r -> Form s
Simple :: (Sat s r) => Pred s -> Marker r -> Form s
Derived :: Form r -> Suffix r s -> Form s
Complex :: (Sat s r, Sat t P) =>
Form s -> Infix r -> Form t -> Form s
data FormA a where
FormA :: (Pred s -> Marker t -> a)
-> (Pred u -> Marker v -> a)
-> (a -> Suffix w x -> a)
-> (a -> y -> a -> a)
-> FormA a
foldForm :: FormA a -> Form s -> a
foldForm [email protected](FormA prim _ _ _) (Prim p m) = prim p m
foldForm [email protected](FormA _ simple _ _) (Simple p m) = simple p m
foldForm [email protected](FormA _ _ derived _) (Derived f s) =
derived (foldForm alg f) s
foldForm [email protected](FormA _ _ _ complex) (Complex f1 i f2) =
complex (foldForm alg f1) i (foldForm alg f2)
適切な定義は 'Alg ::(n - > a) - > ... - > Alg n a' - 型'存在します。 n - > a'は 'a'と同型ですが、関数で唯一できるのはそれを適用するだけなので、' n'型については何も知らないので、この関数を 'undefined'にしか適用できません。しかし、あなたはこれを知っているようです - 「答えが内部変数をデータ型の署名に持ち上げているかもしれません」 "しかし、この例のようにそうではなく、元のコードで使用することはできません" - それはあなたが投稿すべき元のコードです。 – user2407038