Polimorfismo y tipos de datos inductivos

10

Soy curioso. He estado trabajando en este tipo de datos en OCaml :

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

Que se puede manipular utilizando funciones recursivas escritas explícitamente (una característica que se ha agregado recientemente). Ejemplo:

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

Pero nunca he podido definirlo en Coq :

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

Coq se queja. No le gusta el último constructor, y dice algo que no entiendo completamente o no estoy de acuerdo:

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

Lo que puedo entender es que los tipos inductivos que usan una negación dentro de su definición como type 'a term = Constructor ('a term -> …)son rechazados, porque darían lugar a bestias feas no bien fundadas como términos λ (sin tipo). Sin embargo, este exptreetipo de datos en particular parece bastante inocuo: mirando su definición OCaml , su argumento 'anunca se usa en posiciones negativas.

Parece que Coq es demasiado cauteloso aquí. Entonces, ¿hay realmente un problema con este tipo de datos inductivo en particular? ¿O podría Coq ser un poco más permisivo aquí?

Además, ¿qué pasa con otros asistentes de pruebas, son capaces de hacer frente a una definición tan inductiva (de forma natural)?

Stéphane Gimenez
fuente

Respuestas:

9

Esto ha aparecido en la lista de correo de Coq varias veces, pero nunca vi una respuesta concluyente. Coq no es tan general como podría ser; Las reglas en (Coquand, 1990) y (Giménez, 1998) (y su tesis doctoral) son más generales y no requieren una estricta positividad. Sin embargo, la positividad suficiente no es suficiente cuando sales Set; Este ejemplo surgió en varias discusiones :

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

Con estructuras de datos simples como la suya, el tipo inductivo no causaría problemas más que hacer que la implementación sea más compleja.

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

miXpagstrmimi:unmiXpagstrmimi(un)miXpagstrmimi,miXpagstrmimimiXpagstrmimi,miXpagstrmimimiXpagstrmimimiXpagstrmimi,...miXpagstrmimi0 0(un)=unmiXpagstrmimi1(un)=miXpagstrmimi(un)miXpagstrmimi2(un)=miXpagstrmimi(miXpagstrmimi(un))unmiXpagstrmimi0 0(un)=un

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
.

Puede proceder a definir valores y trabajar en ellos. Coq a menudo podrá inferir el exponente. Set Implicit Argumentsharía estas definiciones más bonitas.

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

exptreeet 0S nunun

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)).

Creo que este es el mismo principio propuesto en forma más general por Ralph Mattes .

Referencias

Thierry Coquand y Christine Paulin. Tipos inductivamente definidos . En Actas de COLOG'88 , LNCS 417, 1990. [ Springer ] [ Google ]

Eduardo Giménez. Definiciones recursivas estructurales en la teoría de tipos . En ICALP'98: Actas del 25º Coloquio internacional sobre autómatas, idiomas y programación. Springer-Verlag, 1998. [ PDF ]

Gilles 'SO- deja de ser malvado'
fuente
8

Ralph Matthes describe cómo simular tipos como este en Coq en "Una estructura de datos para poderes iterados" ( código , papel ).

jbapple
fuente
6

Una de las primeras cosas que hace Coq es construir el principio de inducción asociado con el tipo inductivo que acaba de definir y comprender el principio de inducción subyacente es un buen ejercicio.

Por ejemplo O : nat | S : nat -> nat, generará el principio de inducción P O -> (∀ n, P n -> P (S n)) -> ∀ n, P n.

¿Cuál sería el principio de inducción correspondiente iota? Parece que no hay ningún predicado Pque sería capaz de hablar P ty P (iota t), debido a que debe hablar exptree a, exptree (exptree a), exptree (exptree (exptree a))...

También Omicronhace lo mismo pero el tipo es más pequeño cada vez. Debe sentir que tener una referencia tanto a un tipo más pequeño como a un tipo más grande haría que las cosas se complicaran. (Dicho esto, Omicrones la forma correcta)

Ese no es el criterio exacto que dice por qué la definición no debe ser aceptada, pero esto explica por qué me parece mal.

exptreeparece que usted está construyendo una gramática para expresiones, cosa que generalmente no son que recursiva. ¿Quieres ayuda con eso?

jmad
fuente