Equality in definitions (decidable equality? e.g. replace elements in list) - typeclass

I am trying to learn lean and want to define a replace function, which takes two elements x and y and replaces every occurrence of x with y in a given list.
I tried to define it like this:
def replace {α : Type}: α -> α -> list α -> list α
| a b [] := []
| a b (x::xs) := (if a = x then b else x) :: replace a b xs
This gives me the following error:
error: failed to synthesize type class instance for
α : Type,
replace : α → α → list α → list α,
a b x : α,
xs : list α
⊢ decidable (a = x)
My problem is that I cannot use equality for type α, so I guess I need to restrict α to be of some kind of type class where equality is decidable (like I would in Haskell). How can I do this?
My current workaround is to take the equality function as a parameter:
def replace {α : Type}: (α -> α -> bool) -> α -> α -> list α -> list α
| eq a b [] := []
| eq a b (x::xs) := (if eq a x then b else x) :: replace eq a b xs

You can take the decidable equality of α as a type class argument, like this:
def replace {α : Type} [decidable_eq α] : α -> α -> list α -> list α
| a b [] := []
| a b (x::xs) := (if a = x then b else x) :: replace a b xs
#eval replace 2 3 [2, 2, 5, 6, 3, 2]
The square brackets denote that an instance of the type class should be inferred by type class resolution.

Related

Modeling System F's parametric polymorphism at Set₀

In System F, the kind of a polymorphic type is * (as that's the only kind in System F anyway...), so e.g. for the following closed type:
[] ⊢ (forall α : *. α → α) : *
I would like to represent System F in Agda, and because everything is in *, I thought I'd interpret types (like the above) as Agda Sets; so something like
evalTy : RepresentationOfAWellKindedClosedType → Set
However, Agda doesn't have polymorphic types, so the above type, in Agda, would need to be a (large!) Π type:
idType = (α : Set) → α → α
which means it is not in Set₀:
idType : Set
idType = (α : Set) → α → α
poly-level.agda:4,12-29
Set₁ != Set
when checking that the expression (α : Set) → α → α has type Set
Is there a way out of this, or is System F not embeddable in this sense into Agda?
Instead of
evalTy : Type → Set
you can write
evalTy : (σ : Type) -> Set (levelOf σ)
(András Kovács, care to add an answer with references to your embedding of predicative System F?)
This is enough for embedding, but I've seen a lot of Setω errors and they have traumatised me, so now I'm trying to avoid dependent universes as much as possible.
You can embed polymorphic types into Set₁ and monomorphic types into Set, so you can embed any type into Set₁ using the ugly lifting mechanism. I tried this several times and it always was awful.
The thing I would try is to define evalTy as
evalTy : Type -> Set ⊎ Set₁
and then eliminate it at the type level like this:
data [_,_]ᵀ {α β γ δ} {A : Set α} {B : Set β} (C : A -> Set γ) (D : B -> Set δ)
: A ⊎ B -> Set (γ ⊔ δ) where
inj¹ : ∀ {x} -> C x -> [ C , D ]ᵀ (inj₁ x)
inj² : ∀ {y} -> D y -> [ C , D ]ᵀ (inj₂ y)
You can run this elimination:
Runᴸ : ∀ {α β γ δ} {A : Set α} {B : Set β} {C : A -> Set γ} {D : B -> Set δ} {s}
-> [ C , D ]ᵀ s -> Level
Runᴸ {γ = γ} (inj¹ _) = γ
Runᴸ {δ = δ} (inj² _) = δ
Runᵀ : ∀ {α β γ δ} {A : Set α} {B : Set β} {C : A -> Set γ} {D : B -> Set δ} {s}
-> (sᵀ : [ C , D ]ᵀ s) -> Set (Runᴸ sᵀ)
Runᵀ {C = C} (inj¹ {x} _) = C x
Runᵀ {D = D} (inj² {y} _) = D y
runᵀ : ∀ {α β γ δ} {A : Set α} {B : Set β} {C : A -> Set γ} {D : B -> Set δ} {s}
-> (sᵀ : [ C , D ]ᵀ s) -> Runᵀ sᵀ
runᵀ (inj¹ z) = z
runᵀ (inj² w) = w
Thus you introduce a universe dependency only at the end, when you actually need to compute something.
E.g.
SomeSet : ℕ -> Set ⊎ Set₁
SomeSet 0 = inj₁ ℕ
SomeSet n = inj₂ Set
ofSomeSet : ∀ n -> [ (λ A -> A × A) , id ]ᵀ (SomeSet n)
ofSomeSet zero = inj¹ (0 , 5)
ofSomeSet (suc n) = inj² ℕ
-- 0 , 5
test₁ : ℕ × ℕ
test₁ = runᵀ (ofSomeSet 0)
-- ℕ
test₂ : Set
test₂ = runᵀ (ofSomeSet 1)
ofSomeSet is a dependent function, but not a "universally dependent", you can write e.g. f = ofSomeSet ∘ suc and it's a perfectly typeable expression. This doesn't work with universes dependencies:
fun : ∀ α -> Set (Level.suc α)
fun α = Set α
oops = fun ∘ Level.suc
-- ((α : Level) → Set (Level.suc α)) !=< ((y : _B_160 .x) → _C_161 y)
-- because this would result in an invalid use of Setω
You can also enhance [_,_]ᵀ to make it mappable like I did here, but this all is probably overkill and you should just use
evalTy : (σ : Type) -> Set (levelOf σ)
Note that I'm talking only about the predicative fragment of System F. Full System F is not embeddable as Dominique Devriese explains in his comments to the question.
However I feel like we can embed more than the predicative fragment, if we first normalize a System F term. E.g. id [∀ α : *. α → α] id is not directly embeddable, but after normalization it becomes just id, which is embeddable.
However it should be possible to embed id [∀ α : *. α → α] id even without normalization by transforming it into Λ α. id [α → α] (id [α]), which is what Agda does with implicit arguments (right?). So it's not clear to me what exactly we can't embed.

How to make Agda pretty-print products nicely

Consider the following self-contained program:
module Test where
record Σ {A : Set} (B : A -> Set) : Set where
constructor _,_
field
fst : A
snd : B fst
open Σ public
infixr 0 _,_
_×_ : Set -> Set -> Set
A × B = Σ (\ (_ : A) -> B)
infixr 10 _×_
f : {A B : Set} → A × B → A
f x = {!!}
If you C-c C-l in the goal, you get:
Goal: .A
————————————————————————————————————————————————————————————
x : Σ (λ _ → .B)
.B : Set
.A : Set
i.e. you see the underlying sigma, and the type of the binder of the lambda is hidden. This is pretty annoying. Is there a way to make Agda show the type of binders that don't bind names by default?
This is Agda 2.3.2.2.
Agda 2.4.3 displays x : .A × .B.
You can use the abstract keyword:
abstract
_×_ : Set -> Set -> Set
A × B = Σ (\ (_ : A) -> B)
fst' : ∀ {A B} -> A × B -> A
fst' (x , y) = x
snd' : ∀ {A B} -> A × B -> B
snd' (x , y) = y
But that's definitely overkill (and it looks like pattern synonyms do not work in abstract blocks).
It's much more annoying to me, that Agda doesn't want to reduce functions like flip and especially _∘_, but unfolds some functions with really long definitions. Agda needs a mechanism for fixing these problems.
It appears that this problem has been fixed in the latest version of Agda, so you should upgrade.

L-product-0 Theorem

I would like to prove the following:
𝕃-product-0 : ∀{l : 𝕃 ℕ} → list-any (_=ℕ_ 0) l ≡ tt → 𝕃-product l ≡ 0
𝕃-product-0 = {!!}
'list-any' is defined as:
list-any : ∀{ℓ}{A : Set ℓ}(pred : A → 𝔹)(l : 𝕃 A) → 𝔹
list-any pred [] = ff
list-any pred (x :: xs) = pred x || list-any pred xs
And _=ℕ_ is defined as:
_=ℕ_ : ℕ → ℕ → 𝔹
0 =ℕ 0 = tt
suc x =ℕ suc y = x =ℕ y
_ =ℕ _ = ff
I'm trying to understand this part: list-any (_=ℕ_ 0) l ≡ tt
Is (_=ℕ_ 0) ≡ (pred : A → 𝔹) and l ≡ (l : 𝕃 A)?
If so, I would like help understanding the predicate. What does (=ℕ 0) mean? I'm assuming =ℕ is applied like:
Foreach element in l return (element =ℕ 0).
Is this correct? I tried to prove the theorem by using a list l1:
𝕃-product-0 : ∀{l : 𝕃 ℕ} → list-any (_=ℕ_ 0) l ≡ tt → 𝕃-product l ≡ 0
𝕃-product-0 l1 = {!!}
but got the following error:
I'm not sure if there should be a case for the constructor refl,
because I get stuck when trying to solve the following unification
problems (inferred index ≟ expected index):
list-any (_=ℕ_ 0) l ≟ tt
when checking that the expression ? has type 𝕃-product .l ≡ 0
I appreciate any help given!
Edit (response 1):
I split the the case on the hole and got:
𝕃-product-0 : ∀{l : 𝕃 ℕ} → list-any (_=ℕ_ 0) l ≡ tt → 𝕃-product l ≡ 0
𝕃-product-0 x = {!!}
Is this the case that I want? It filled in x when I split.
It can also see that:
Goal: 𝕃-product .l ≡ 0
Where:
x : list-any (_=ℕ_ 0) .l ≡ tt
.l : 𝕃 ℕ
What is the program wanting me to solve at this point? How can I show that
𝕃-product-0 x is logically equivalent to 𝕃-product .l ≡ 0?
I'm trying to understand this part: list-any (=ℕ 0) l ≡ tt
Is (=ℕ 0) ≡ (pred : A → 𝔹) and l ≡ (l : 𝕃 A)?
You're correct in that _=ℕ_ 0 is substituted for pred. _=ℕ_ 0 means the result of applying the function _=ℕ_ to 0. Since _=ℕ_ is a binary function, applying it to just one argument yields a function ℕ -> 𝔹, which is what list-any expects.
As to the other question, you're trying to pattern match there on l, but it's implicit: in your example l1 actually denotes the list-any (_=ℕ_ 0) l ≡ tt argument, because that's the first explicit argument. You have to introduce the implicit argument using brackets:
𝕃-product-0 : ∀{l : 𝕃 ℕ} → list-any (_=ℕ_ 0) l ≡ tt → 𝕃-product l ≡ 0
𝕃-product-0 {l1} = {!!}
Edit:
I assume you're in Emacs agda-mode. When you look at the the context, the implicit arguments are prefixed with a dot, like .l : 𝕃 ℕ. If you're on a new-ish Agda, if you want to split on .l, write { .l } in the hole, then hit C-c-c. Another solution is to introduce the argument in the function definition using brackets, like how I wrote above, then write { l1 } in the hole, then hit C-c-c.
Alternatively, you can make the list argument explicit and save yourself the brackets:
𝕃-product-0 : (l : 𝕃 ℕ) → list-any (_=ℕ_ 0) l ≡ tt → 𝕃-product l ≡ 0
𝕃-product-0 l = ?
Just remember that in a function definition, arguments without brackets are the explicit arguments, and you can insert implicit arguments before or between them corresponding to the order they appear in the type. You can also refer to implicit arguments by their name in the type. For example:
foo : Nat -> {l : list Nat} -> Nat -> Nat
foo n m = ? -- now "n" refers to the first Nat and "m" refers to the last argument
foo : Nat -> {l : list Nat} -> Nat -> Nat
foo n {l} m = ? -- now "l" refers to the list.
foo : Nat -> {l : list Nat} -> Nat -> Nat
foo n {l = list} m = ? -- refer to "l" by the name "list" here.

Arbitrary evaluation in the type signature in agda

So I have another "simple" Adga question. I wanted to have a proof that used arbitrary evaluations as premises and results. But I don't think I know the type system well enough to do that.
as a simple example take
f : {S : Set} -> (a : S)
-> ( R : S -> Set)
-> (R a)
f aa rr = rr aa
which has a compilation error
Set !=< rr aa of type Set1
when checking that the expression rr aa has type rr aa
of course
f : {S : Set} -> (a : S)
-> ( R : S -> Set)
-> Set
f aa rr = rr aa
compiles fine
as does
f : {S : Set} -> (a : S)
-> ( R : S -> Set)
-> (R a)
-> (R a)
f _ _ ra = ra
What does (R a) means in context? Can it be constructed? How can it be constructed?
In your first example the expression rr aa has type Set, because it is the result of the application of aa of type S to the function rr of type S -> Set.
The type signature of your function demands a result type of R a though. Given the naming of your parameters the expected result type is rr aa. The type checker now tries to unify the expected type (rr aa) with the expression type (Set) and fails.
In fact a function of the type given above would be inconsistent with the type theory:
no-f : (f : {S : Set} → (a : S) → (R : S → Set) → R a) → ⊥
no-f f = f tt (λ _ → ⊥)
In other words, assuming there was a function of the type above, an element of the empty type (⊥) could be produced. So in general you cannot construct elements of type R a without additional requirements.
Imports used above:
open import Data.Empty
open import Data.Unit

Instance Implicits for Type Checking

I am learning how "typeclasses" are implemented in Agda. As an example, I am trying to implement Roman numerals whose composition with # would type-check.
I am not clear why Agda complains there is no instance for Join (Roman _ _) (Roman _ _) _ - clearly, it couldn't work out what natural numbers to substitute there.
Is there a nicer way to introduce Roman numbers that don't have "constructor" form? I have a constructor "madeup", which probably would need to be private, to be sure I have only "trusted" ways to construct other Roman numbers through Join.
module Romans where
data ℕ : Set where
zero : ℕ
succ : ℕ → ℕ
infixr 4 _+_ _*_ _#_
_+_ : ℕ → ℕ → ℕ
zero + x = x
succ y + x = succ (y + x)
_*_ : ℕ → ℕ → ℕ
zero * x = zero
succ y * x = x + (y * x)
one = succ zero
data Roman : ℕ → ℕ → Set where
i : Roman one one
{- v : Roman one five
x : Roman ten one
... -}
madeup : ∀ {a b} (x : Roman a b) → (c : ℕ) → Roman a c
record Join (A B C : Set) : Set where
field jo : A → B → C
two : ∀ {a} → Join (Roman a one) (Roman a one) (Roman a (one + one))
two = record { jo = λ l r → madeup l (one + one) }
_#_ : ∀ {a b c d C} → {{j : Join (Roman a b) (Roman c d) C}} → Roman a b → Roman c d → C
(_#_) {{j}} = Join.jo j
-- roman = (_#_) {{two}} i i -- works
roman : Roman one (one + one)
roman = {! i # i!} -- doesn't work
Clearly, if I specify the implicit explicitly, it works - so I am confident it is not the type of the function that is wrong.
Your example works fine in development version of Agda. If you are using a version older than 2.3.2, this passage from release notes could clarify why it doesn't compile for you:
* Instance arguments resolution will now consider candidates which
still expect hidden arguments. For example:
record Eq (A : Set) : Set where
field eq : A → A → Bool
open Eq {{...}}
eqFin : {n : ℕ} → Eq (Fin n)
eqFin = record { eq = primEqFin }
testFin : Bool
testFin = eq fin1 fin2
The type-checker will now resolve the instance argument of the eq
function to eqFin {_}. This is only done for hidden arguments, not
instance arguments, so that the instance search stays non-recursive.
(source)
That is, before 2.3.2, the instance search would completly ignore your two instance because it has a hidden argument.
While instance arguments behave a bit like type classes, note that they will only commit to an instance if there's only one type correct version in scope and they will not perform a recursive search:
Instance argument resolution is not recursive. As an example,
consider the following "parametrised instance":
eq-List : {A : Set} → Eq A → Eq (List A)
eq-List {A} eq = record { equal = eq-List-A }
where
eq-List-A : List A → List A → Bool
eq-List-A [] [] = true
eq-List-A (a ∷ as) (b ∷ bs) = equal a b ∧ eq-List-A as bs
eq-List-A _ _ = false
Assume that the only Eq instances in scope are eq-List and eq-ℕ.
Then the following code does not type-check:
test = equal (1 ∷ 2 ∷ []) (3 ∷ 4 ∷ [])
However, we can make the code work by constructing a suitable
instance manually:
test′ = equal (1 ∷ 2 ∷ []) (3 ∷ 4 ∷ [])
where eq-List-ℕ = eq-List eq-ℕ
By restricting the "instance search" to be non-recursive we avoid
introducing a new, compile-time-only evaluation model to Agda.
(source)
Now, as for the second part of the question: I'm not exactly sure what your final goal is, the structure of the code ultimately depends on what you want to do once you construct the number. That being said, I wrote down a small program that allows you to enter roman numerals without going through the explicit data type (forgive me if I didn't catch your intent clearly):
A roman numeral will be a function which takes a pair of natural numbers - the value of previous numeral and the running total. If it's smaller than previous numeral, we'll subtract its value from the running total, otherwise we add it up. We return the new running total and value of current numeral.
Of course, this is far from perfect, because there's nothing to prevent us from typing I I X and we end up evaluating this as 10. I leave this as an exercise for the interested reader. :)
Imports first (note that I'm using the standard library here, if you do not want to install it, you can just copy the definition from the online repo):
open import Data.Bool
open import Data.Nat
open import Data.Product
open import Relation.Binary
open import Relation.Nullary.Decidable
This is our numeral factory:
_<?_ : Decidable _<_
m <? n = suc m ≤? n
makeNumeral : ℕ → ℕ × ℕ → ℕ × ℕ
makeNumeral n (p , c) with ⌊ n <? p ⌋
... | true = n , c ∸ n
... | false = n , c + n
And we can make a few numerals:
infix 500 I_ V_ X_
I_ = makeNumeral 1
V_ = makeNumeral 5
X_ = makeNumeral 10
Next, we have to apply this chain of functions to something and then extract the running total. This is not the greatest solution, but it looks nice in code:
⟧ : ℕ × ℕ
⟧ = 0 , 0
infix 400 ⟦_
⟦_ : ℕ × ℕ → ℕ
⟦ (_ , c) = c
And finally:
test₁ : ℕ
test₁ = ⟦ X I X ⟧
test₂ : ℕ
test₂ = ⟦ X I V ⟧
Evaluating test₁ via C-c C-n gives us 19, test₂ then 14.
Of course, you can move these invariants into the data type, add new invariants and so on.

Resources