Agda, tipo de pruebas y con clausula

En AgdaIntro, la sección de vista explica:

..esecon no recuerda la conexión entre el término temporal y los patrones.

Eso significa cuando define

data   False : Set where
record True  : Set where

isTrue : Bool -> Set
isTrue true  = True
isTrue false = False

infixr 30 _:all:_
data All {A : Set}(P : A -> Set) : List A -> Set where
  all[]   : All P []
  _:all:_ : forall {x xs} -> P x -> All P xs -> All P (x :: xs) 

satisfies : {A : Set} -> (A -> Bool) -> A -> Set
satisfies p x = isTrue (p x)

data Find {A : Set}(p : A -> Bool) : List A -> Set where
  found : (xs : List A)(y : A) -> satisfies p y -> (ys : List A) -> 
           Find p (xs ++ y :: ys)
  not-found : forall {xs} -> All (satisfies (not � p)) xs -> 
              Find p xs

Y quieres probar

find1 :{A:Set}(p:A->Bool)(xs:ListA)->Find p xs 
find1 p [] = not-found all []
find1 p(x::xs) with p x
...| true  = found [] x {!!} xs
...| false = {!!}

El tipo de agujero ({!!}) Es Verdadero (p x), aunque ya coincidimos con p x y descubrimos que era cierto.

¡El compilador no es consciente de que hicimos una coincidencia de patrones en p x y nos pide una prueba de que p x es cierto!

Esto motiva la introducción de un nuevo tipo, el

..tipo de elementos de un tipo A junto con pruebas de que son iguales a alguna x dada en A.

,
data Inspect {A : Set}(x : A) : Set where
  it : (y : A) -> x == y -> Inspect x

inspect : {A : Set}(x : A) -> Inspect x
inspect x = it x refl

Con este tipo, la función find se puede escribir:

trueIsTrue : {x : Bool} -> x == true -> isTrue x
trueIsTrue refl = _

falseIsFalse : {x : Bool} -> x == false -> isFalse x
falseIsFalse refl = _

find : {A : Set}(p : A -> Bool)(xs : List A) -> Find p xs
find p [] = not-found all[]
find p (x :: xs) with inspect (p x)
... | it true prf = found [] x (trueIsTrue prf) xs
... | it false prf with find p xs
find p (x :: ._) | it false _   | found xs y py ys =
  found (x :: xs) y py ys
find p (x :: xs) | it false prf | not-found npxs =
  not-found (falseIsFalse prf :all: npxs)

AHORA, si quiero probar la siguiente propiedad:

predicate : ∀ {A : Set} {p : A -> Bool } {xs : List A } -> 
            All (satisfies' p) (filter p xs)

Tendré el mismo problema que con find, así que necesito una coincidencia de patrón en la inspección para obtener un testigo, pero yoADEMÁS necesita tener el compilador para progresar en el filtro en el casop x == true !

Si hago una coincidencia de patrones paralelos, el compilador los trata como expresiones independientes

predicate {A} {p} {xs = []} = all[]
predicate {A} {p} {xs = x :: xs} with p x
predicate {A} {p} {x :: xs} | px with  inspect (p x) 
predicate {A} {p} {x :: xs} | true | it true pf = {!!}
predicate {A} {p} {x :: xs} | true | it false pf = {!!} 
predicate {A} {p} {x :: xs} | false | it true pf = {!!}
predicate {A} {p} {x :: xs} | false | it false pf = {!!}

¿Cómo puedo decirle al compilador que las dos ramas están vinculadas de alguna manera? ¿Debo agregar una prueba de ello?

Respuestas a la pregunta(1)

Su respuesta a la pregunta