P r o p es muy útil para la extracción de programas porque nos permite eliminar partes de código que son inútiles. Por ejemplo, para extraer un algoritmo de clasificación, probaríamos la declaración "para cada lista hay una lista tal que está ordenada es una permutatiom de ". Si escribimos esto en Coq y lo extraemos sin usar , obtendremos:k k k ℓ P r o pℓkkkℓP r o p
- "para todos hay " nos dará un mapa que lleva listas a listas,kℓk
sort
- "tal que se ordene " dará una función que corre a través de y verifica que esté ordenada, ykk
verify
k
- " es una permutación de " dará una permutación que lleva a . Tenga en cuenta que no es solo un mapeo, sino también el mapeo inverso junto con programas que verifican que los dos mapas son realmente inversos.ℓ ℓ kkℓ
pi
ℓkpi
Si bien el material adicional no es totalmente inútil, en muchas aplicaciones queremos deshacernos de él y mantenernos justos sort
. Esto se puede lograr si usamos para indicar " está ordenado" y " es una permutación de ", pero no "para todos hay ". k k ℓ ℓ kP r o pkkℓℓk
En general, una forma común de extraer código es considerar una declaración de la forma donde es input, es salida, y explica lo que significa que sea una salida correcta. (En el ejemplo anterior, y son los tipos de listas y es " está ordenado es una permutación de ".) Si está en entonces extracción da un mapa tal que cumple para todosx y ϕ ( x , y ) y A B ϕ ( ℓ , k ) k k ℓ ϕ P r o p f : A → B ϕ ( x , f ( x ) ) x ∈ A ϕ S e t g g ( x ) ϕ ( x ,∀ x : A.∃ y: B.ϕ ( x , y)Xyϕ ( x , y)yUNAsiϕ ( ℓ , k )kkℓϕPropf:A→Bϕ(x,f(x))x∈A . Si es decir en entonces también obtenemos una función tal que es la prueba de que sostiene, por todo . A menudo, la prueba es computacionalmente inútil y preferimos deshacernos de ella, especialmente cuando está anidada profundamente en alguna otra declaración. nos da la posibilidad de hacerlo.ϕSetgg(x)x ∈ A P r o pϕ(x,f(x))x∈AProp
Agregado 2015-07-29: Hay una pregunta sobre si podríamos evitar por completo al optimizar automáticamente el "código extraído inútil". Hasta cierto punto podemos hacer eso, por ejemplo, todo el código extraído del fragmento negativo de la lógica (material construido a partir del tipo vacío, tipo de unidad, productos) es inútil ya que simplemente se baraja alrededor de la unidad. Pero hay decisiones de diseño genuinas que uno debe tomar al usar . Aquí hay un ejemplo simple, donde significa que estamos en y significa que estamos en . Si extraemos de
P r o p Σ T y p e ∃ P r o p Π n : N Σ b : { 0 , 1 } Σ k : NPropPropΣType∃Propn b k Π n : N Σ b : { 0 , 1 } ∃ k : N
Πn:NΣb:{0,1}Σk:Nn=2⋅k+b
obtendremos un programa que descompone en su bit más bajo y los bits restantes , es decir, computa todo. Si extraemos de
entonces el programa solo calculará el bit más bajo . La máquina no puede decir cuál es la correcta, el usuario tiene que decirle lo que quiere.
nbkbΠn:NΣb:{0,1}∃k:Nn=2⋅k+b
b