How to get around the implicit vs explicit function type error?

234 Views Asked by At

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.

2

There are 2 best solutions below

0
Marko Grdinić On

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
0
Shreck Ye On

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