GADTとデータ型を組み合わせるのが本当に好きです。以前よりも型の安全性が向上しています(ほとんどの場合、AgqなどのCoqとほとんど同じです)。悲しいことに、最も単純な例ではパターンマッチングは失敗し、型クラス以外の関数を書く方法はないと思います。GADTとデータ型のHaskellパターンマッチング
は、ここに私の悲しみを説明するための例です:
data Nat = Z | S Nat deriving Eq
data Le :: Nat -> Nat -> * where
Le_base :: Le a a
Le_S :: Le a b -> Le a (S b)
class ReformOp n m where
reform :: Le (S n) (S m) -> Le n m
instance ReformOp a a where
reform Le_base = Le_base
instance ReformOp a b => ReformOp a (S b) where
reform (Le_S p) = Le_S $ reform p
class TransThm a b c where
trans :: Le a b -> Le b c -> Le a c
instance TransThm a a a where
trans = const
instance TransThm a a b => TransThm a a (S b) where
trans Le_base (Le_S p) = Le_S $ trans Le_base p
instance (TransThm a b c, ReformOp b c) => TransThm a (S b) (S c) where
trans (Le_S p) q = Le_S $ trans p $ reform q
私たちは、2型クラス(定理のための1つのユーティリティ操作のための1)と5つのインスタンスを持っている - ちょうど些細な定理のために。呼び出すとき
-- not working, I understand why
trans :: Le a b -> Le b c -> Le a c
trans Le_base Le_base = Le_base
trans Le_base (Le_S p) = Le_S $ trans Le_base p
trans (Le_S p) q = Le_S $ trans p $ reform q
そして独自に各句をタイプチェック、および(一致しようとしているので、価値が)可能である場合を決めるごとの呼び出し、どのように、ではありません。理想的には、Haskellはこの機能で見ることができますtrans Le_base Le_base
Haskellは、最初のケースだけが3つの変数が同じであることを許し、最初の句で一致を試みることに気づくでしょう。
、あなたは正しいです! –