De esta referencia: positividad estricta
La condición de positividad estricta descarta declaraciones como
data Bad : Set where
bad : (Bad → Bad) → Bad
A B C
-- A is in a negative position, B and C are OK
¿Por qué A es negativo? ¿También por qué B está permitido? Entiendo por qué C está permitido.
type-theory
inductive-datatypes
Pushpa
fuente
fuente

Ay explotar la pila eventualmente (en lenguajes basados en pila).Respuestas:
Primero una explicación terminológica: las posiciones negativas y positivas provienen de la lógica. Son alrededor de una asimetría en conectores lógicos: en al A se comporta de manera diferente de B . Algo similar sucede en la teoría de categorías, donde decimos contravariante y covariante en lugar de negativo y positivo, respectivamente. En física, hablan de cantidades que se comportan "covariablemente" y "contrariamente, también. Así que este es un fenómeno muy general. Un programador podría pensar en ellas como" entrada "y" salida ".A ⇒ B UN si
Ahora en tipos de datos inductivos.
Piensa en un tipo de datos inductiva como una especie de estructura algebraica: constructores son las operaciones que tienen elementos de T como argumentos y producen nuevos elementos de T . Esto es muy similar al álgebra ordinaria: la suma toma dos números y produce un número.T T T
En álgebra, es costumbre que una operación tome un número finito de argumentos, y en la mayoría de los casos toma cero (constante), uno (unario) o dos (binarios) argumentos. Es conveniente generalizar esto para constructores de tipos de datos. Supongamos que
ces un constructor para un tipo de datosT:ces una constante, podemos pensar en ella como una funciónunit -> T, o de manera equivalente(empty -> T) -> T,ces unario, podemos considerarlo como una funciónT -> T, o de manera equivalente(unit -> T) -> T,ces binario, podemos considerarlo como una funciónT -> T -> T, o de manera equivalenteT * T -> To equivalente(bool -> T) -> T,cque tomara siete argumentos, podríamos verlo como una función(seven -> T) -> Tdondesevenhay algún tipo previamente definido con siete elementos.cque tome innumerables argumentos, que sería una función(nat -> T) -> T.Estos ejemplos muestran que la forma general de un constructor debe ser
donde llamamos a
Ala aridad decy pensamos queces un constructor que tomaA-muchos argumentos de tipoTpara producir un elemento deT.Aquí hay algo muy importante: las aridades deben definirse antes de que las definamos
T, o de lo contrario no podemos saber qué deben hacer los constructores. Si alguien intenta tener un constructorentonces la pregunta "¿cuántos argumentos
brokenlleva?" No tiene una buena respuesta. Puede intentar responderlo con "se necesitanTmuchos argumentos", pero eso no servirá, porqueTaún no está definido. Podríamos tratar de salir del cunundrum usando una teoría elegante de punto fijo para encontrar un tipoTy una función inyectiva(T -> T) -> T, y tendríamos éxito, pero también romperíamos el principio de inducción enTel camino. Entonces, es una mala idea intentar tal cosa.cBDe hecho, muchos constructores se pueden reescribir de esta forma, pero no todos, necesitamos un paso más, es decir, debemos permitir
Aque dependerá deB:Esta es la forma final de un constructor para un tipo inductivo. También es precisamente lo que son los tipos W. ¡La forma es tan general que solo necesitamos un solo constructor
c! De hecho, si tenemos dos de ellosentonces podemos combinarlos en uno
dónde
Por cierto, si cambiamos la forma general, vemos que es equivalente a
que está más cerca de lo que la gente realmente escribe en asistentes de prueba. Los asistentes de prueba nos permiten escribir los constructores de manera conveniente, pero son equivalentes a la forma general anterior (¡ejercicio!).
fuente
La primera aparición de
Badse llama 'negativa' porque representa un argumento de función, es decir, se encuentra a la izquierda de la flecha de función (vea Philip Wadler los tipos recursivos de forma gratuita ). Supongo que el origen del término 'posición negativa' proviene de la noción de contravarianza ('contra' significa opuesto).No se permite que el tipo se defina en posición negativa porque uno puede escribir programas sin terminación usándolo, es decir, una fuerte normalización falla en su presencia (más sobre esto a continuación). Por cierto, esta es la razón del nombre de la regla 'positividad estricta': no permitimos posiciones negativas.
Permitimos la segunda aparición de,
Badya que no causa la no terminación y queremos usar el tipo que se define (Bad) en algún momento en un tipo de datos recursivo ( antes de la última flecha de su constructor).Es importante comprender que la siguiente definición no viola la estricta regla de positividad.
La regla se aplica solo a los argumentos del constructor (que son ambos
Gooden este caso) y no a un constructor en sí mismo (véase también " Programación certificada con tipos dependientes " de Adam Chlipala ).Otro ejemplo que viola la positividad estricta:
También es posible que desee verificar esta respuesta sobre las posiciones negativas.
Más información sobre la no terminación ... La página a la que hizo referencia contiene algunas explicaciones (junto con un ejemplo en Haskell):
Aquí hay un ejemplo análogo en Ocaml, que muestra cómo implementar un comportamiento recursivo sin (!) Usando la recursión directamente:
La
nonTerminatingfunción "desempaqueta" una función de su argumento y la transfiere al argumento original. Lo importante aquí es que la mayoría de los sistemas de tipos no permiten pasar funciones a sí mismos, por lo que un término comof fno mecanografiará, ya que no hay ningún tipo parafsatisfacer el mecanografiado. Una de las razones por las que se introdujeron los sistemas de tipos es para deshabilitar la auto aplicación (ver aquí ).Los tipos de datos de envoltura como el que presentamos anteriormente se pueden usar para sortear este obstáculo en el camino hacia la inconsistencia.
Quiero agregar que los cálculos sin terminación introducen inconsistencias en los sistemas lógicos. En el caso de Agda y Coq, el
Falsetipo de datos inductivo no tiene ningún constructor, por lo que nunca se puede construir un término de prueba de tipo False. Pero si se permitieran los cálculos sin terminación, uno podría hacerlo, por ejemplo, de esta manera (en Coq):Luego
loop 0escribiría chequesloop 0 : False, por lo que, según la correspondencia de Curry-Howard, significaría que probamos una proposición falsa.Resultado : la estricta regla de positividad para las definiciones inductivas evita los cálculos sin terminación que son desastrosos para la lógica.
fuente