ポリモーフィズムと帰納的データ型


10

私は興味がある。私はOCamlでこのデータ型に取り組んできました:

type 'a exptree =
  | Epsilon
  | Delta of 'a exptree * 'a exptree
  | Omicron of 'a
  | Iota of 'a exptree exptree

これは、明示的に型指定された再帰関数(ごく最近追加された機能)を使用して操作できます。例:

let rec map : 'a 'b. ('a -> 'b) -> 'a exptree -> 'b exptree =
  fun f ->
    begin function
    | Epsilon -> Epsilon
    | Delta (t1, t2) -> Delta (map f t1, map f t2)
    | Omicron t -> Omicron (f t)
    | Iota tt -> Iota (map (map f) tt)
    end

しかし、私はそれをCoqで定義することはできませんでした:

Inductive exptree a :=
  | epsilon : exptree a
  | delta : exptree a -> exptree a -> exptree a
  | omicron : a -> exptree a
  | iota : exptree (exptree a) -> exptree a
.

コックは泣き言を言う。それは最後のコンストラクタを好きではなく、私が完全に理解または同意していない何かを言います:

Error: Non strictly positive occurrence of "exptree" in "exptree (exptree a) -> exptree a".

私が理解できることは、定義内で否定を使用するような誘導型type 'a term = Constructor ('a term -> …)は、(型付けされていない)λ項のような醜い非根拠のある獣につながるため、拒否されるということです。ただし、この特定のexptreeデータ型は無害であるように見えます。OCaml定義を見ると、その引数'aは負の位置で使用されることはありません。

と思われるコックがここにovercautiousです。それでは、この特定の帰納的データ型に本当に問題があるのでしょうか?または、Coqの方が少し許容範囲が広いでしょうか?

また、他の証明アシスタントについてはどうですか?彼らはそのような帰納的な定義に(自然な方法で)対処できますか?

回答:


9

これはCoqメーリングリストで何度か出てきましたが、決定的な答えは見たことがありません。Coqは一般的なものではありません。(Coquand、1990)と(Giménez、1998)(および彼の博士論文)の規則はより一般的であり、厳密な積極性を必要としません。しかし、あなたが外に出るとき、十分な陽性は十分ではありませんSet。この例はいくつかの議論で出てきました:

Inductive Big : Type := B : ((B -> Prop) -> Prop) -> Big.

あなたのような単純なデータ構造では、帰納型は実装をより複雑にする以外に問題を引き起こしません。

F=ϵ+δ(F×F)+οid+FF

exptree:aexptree(a)exptree,exptreeexptree,exptreeexptreeexptree,exptree0(a)=aexptree1(a)=exptree(a)exptree2(a)=exptree(exptree(a))aexptree0(a)=a

Inductive et : nat -> Type -> Type :=
  | alpha : forall a, a -> et 0 a                      (*injection*)
  | omicron : forall n a, et n a -> et (S n) a         (**)
  | epsilon : forall (S n) a, et (S n) a
  | delta : forall n a, et (S n) a -> et (S n) a -> et (S n) a
  | iota : forall n a, et (S (S n)) a -> et (S n) a
.

値を定義して作業することができます。Coqは、指数を推測できることがよくあります。Set Implicit Argumentsこれらの定義はよりきれいになります。

Definition exptree := et 1.
Definition et1 : exptree nat :=
  delta _ _ (omicron _ _ (alpha _ 42)) (epsilon _ _).
Definition et2 : exptree nat := iota _ _ (omicron _ _ et1).

exptreeet 0S naa

Inductive et : nat -> Type -> Type :=
  | omicron_0 : forall a, a -> et 0 a
  | omicron_S : forall n a, et n a -> et (S n) a
  | epsilon : forall n a, et n a
  | delta : forall n a, et n a -> et n a -> et n a
  | iota : forall n a, et (S n) a -> et n a
.
Definition exptree := et 0.
Definition et1 : exptree nat :=
  delta _ _ (omicron_0 _ 42) (epsilon _ _).
Definition et2 : exptree nat :=
  (iota _ _ (omicron_S _ _ et1)).

これは、ラルフマットがより一般的な形で提案したのと同じ原理だと思います。

参考文献

ティエリーコカンドとクリスティンパウリン。帰納的に定義されたタイプ。でCOLOG'88の議事録、LNCS 417、1990年[ スプリンガー ] [ グーグル ]

エドゥアルドヒメネス 型理論における構造再帰的定義。でICALP'98:オートマトンの第25回国際コロキアムの議事録、言語とプログラミング。Springer-Verlag、1998年。 [ PDF ]


8

Ralph MatthesがCoqでこのような型をシミュレートする方法については、「反復型パワーのデータ構造」(コードペーパー)で説明しています。


6

Coqが最初に行うことの1つは、先ほど定義した帰納型に関連する帰納原理を構築することであり、基礎となる帰納原理を理解することは良い練習です。

たとえばO : nat | S : nat -> nat、誘導原理を生成しP O -> (∀ n, P n -> P (S n)) -> ∀ n, P nます。

に対応する帰納原理は何でしょうiotaか?それは、述語がないように思わPについて話すことができるであろうP tP (iota t)、それは話すべきであるので、exptree aexptree (exptree a)exptree (exptree (exptree a))...

また、Omicron同じことを行いますが、タイプは毎回小さくなります。小さい型と大きい型の両方への参照があると、事態が複雑になると感じるはずです。(それOmicronは正しい方法です)

それはなぜ定義が受け入れられないのかを示す正確な基準ではありませんが、これはなぜそれが私に間違っていると感じるのかを説明しています。

exptreeあなたが一般的ではないことを、事を式の文法を構築しているように思えることを再帰的。あなたはそれについて何か助けが必要ですか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.