This is from the last chapter of PLFA book.
import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; sym; trans; cong)
open import Data.Product using (_×_; ∃; ∃-syntax; Σ; Σ-syntax) renaming (_,_ to ⟨_,_⟩)
infix 0 _≃_
record _≃_ (A B : Set) : Set where
field
to : A → B
from : B → A
from∘to : ∀ (x : A) → from (to x) ≡ x
to∘from : ∀ (y : B) → to (from y) ≡ y
open _≃_
data List (A : Set) : Set where
[] : List A
_∷_ : A → List A → List A
infixr 5 _∷_
data All {A : Set} (P : A → Set) : List A → Set where
[] : All P []
_∷_ : ∀ {x : A} {xs : List A} → P x → All P xs → All P (x ∷ xs)
data Any {A : Set} (P : A → Set) : List A → Set where
here : ∀ {x : A} {xs : List A} → P x → Any P (x ∷ xs)
there : ∀ {x : A} {xs : List A} → Any P xs → Any P (x ∷ xs)
infix 4 _∈_
_∈_ : ∀ {A : Set} (x : A) (xs : List A) → Set
x ∈ xs = Any (x ≡_) xs
All-∀ : ∀ {A : Set} {P : A → Set} {xs} → All P xs ≃ (∀ {x} → x ∈ xs → P x)
All-∀ {A} {P} =
record { to = to'
; from = from'
; from∘to = from∘to'
; to∘from = to∘from'
}
where
to' : ∀ {xs} → All P xs → (∀ {x} → x ∈ xs → P x)
from' : ∀ {xs} → (∀ {x} → x ∈ xs → P x) → All P xs
from∘to' : ∀ {xs : List A} → (x : All P xs) → from' (to' x) ≡ x
to∘from' : ∀ {xs : List A} → (x∈xs→Px : ∀ {x} → x ∈ xs → P x) → to' (from' x∈xs→Px) ≡ x∈xs→Px
When I fill in the hole with to (from x∈xs→Px) ≡ x∈xs→Px, I get the following error.
_x_1668 (x∈xs→Px = x∈xs→Px) ∈ xs → P (_x_1668 (x∈xs→Px = x∈xs→Px))
!= {x : A} → x ∈ xs → P x because one is an implicit function type
and the other is an explicit function type
when checking that the expression to∘from has type
(y : {x : A} → x ∈ xs → P x) → to (from y) ≡ y
I am not sure what this means, but Agda can be iffy when implicit arguments get involved. The one thing I have not tried is replacing {x} with (x) in ∀ {x} → x ∈ xs → P x because it is a part of the problem definition.
What should the type signature be here? Also is there an easier way of doing this than a where block for every function in the isomorphism? I dislike the heavy copying of the type signatures.
Even with what @gallais said on the Agda page it took me almost 3 hours to figure out how to do this. Here is what I'd recommend the type signature to be. I ran into a lot trouble with functional extensionality. The actual problem was trivial in comparison.
I think the way inference works for implicit arguments could definitely use some maintenance.
postulate
extensionality : ∀ {A : Set} {B : A → Set} {f g : (x : A) → B x}
→ (∀ (x : A) → f x ≡ g x)
-----------------------
→ f ≡ g
postulate
extensionality_impl : ∀ {X : Set}{Y : X → Set}
→ {f g : {x : X} → Y x}
→ ((x : X) → f {x} ≡ g {x})
→ (λ {x} → f {x}) ≡ g
All-∀ : ∀ {A : Set} {P : A → Set} {xs} → All P xs ≃ (∀ {x} → x ∈ xs → P x)
All-∀ {A} {P} =
record { to = to
; from = from
; from∘to = from∘to
; to∘from = λ x'∈xs→Px → extensionality_impl λ x → extensionality λ x∈xs → to∘from x'∈xs→Px x∈xs
}
where
to : ∀ {xs} → All P xs → (∀ {x} → x ∈ xs → P x)
from : ∀ {xs} → (∀ {x} → x ∈ xs → P x) → All P xs
from∘to : ∀ {xs : List A} → (x : All P xs) → from (to x) ≡ x
to∘from : ∀ {xs : List A} (x∈xs→Px : ∀ {x} → x ∈ xs → P x) {x} (x∈xs : x ∈ xs) → to (from x∈xs→Px) x∈xs ≡ x∈xs→Px x∈xs
I have explored some alternatives based on Marko Grdinic's answer to make the code more readable and simpler.
First I have found a slightly simpler way to define extensionality for an implicit argument using extensionality from the library:
open import Axiom.Extensionality.Propositional using (ExtensionalityImplicit)
open Level using (0ℓ)
postulate
extensionality-implicit-0ℓ : ExtensionalityImplicit 0ℓ 0ℓ
And an implicit version of cong-app seems to be also needed for this exercise:
cong-app-implicit : ∀ {A : Set} {B : A → Set} {f g : {x : A} → B x} →
(λ {x} → f {x}) ≡ (λ {x} → g {x}) → {x : A} → f {x} ≡ g {x}
cong-app-implicit refl = refl
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With