Branch on equality test in Agda? (basic) - agda

A very basic question, but as an Agda beginner I'm stumped.
I just want to check if two terms are equal and return different things based on the different cases. I could write my own equality tester, but how do I do this using equiv (or what is the proper way to do it)?
This is a minimal example:
import Data.Nat
import Relation.Binary
myeqtest : ℕ → ℕ → ℕ
myeqtest x y = if x Data.Nat.≟ y then true else false
Error message:
.Relation.Nullary.Core.Dec (x .Relation.Binary.Core.Dummy.≡ y) !=<
Bool of type Set
when checking that the expression x Data.Nat.≟ y has type Bool
I actually want to do something more complicated of course (I know that the above is redundant in several ways), but the point is that x \?= y is not of type Bool, it is of type Set, and I don't know how to turn that Set into a Bool. Thanks.

Boring imports:
open import Relation.Nullary
open import Relation.Nullary.Decidable
open import Relation.Binary.Core
open import Data.Bool hiding (_≟_)
open import Data.Nat
Now let's ask Agda, what she thinks:
myeqtest : ℕ -> ℕ -> Bool
myeqtest x y = {!x ≟ y!}
C-C C-d in the hole gives Dec (x ≡ y). Dec is about decidable propositions and defined in the Relation.Nullary.Core module:
data Dec {p} (P : Set p) : Set p where
yes : ( p : P) → Dec P
no : (¬p : ¬ P) → Dec P
I.e. there always exists a proof of either P or ¬ P, where ¬ means "not". This is just a handmade law of excluded middle for some proposition. In our case there always exists a proof, that one number is either equal or non-equal to another.
So Dec has two contructors: yes and no, and you can use them in pattern-matching:
myeqtest : ℕ -> ℕ -> Bool
myeqtest x y with x ≟ y
... | yes _ = true
... | no _ = false
There is a function in the Relation.Nullary.Decidable module, that turns a Dec into a Bool:
⌊_⌋ : ∀ {p} {P : Set p} → Dec P → Bool
⌊ yes _ ⌋ = true
⌊ no _ ⌋ = false
So you can define myeqtest as
myeqtest : ℕ -> ℕ -> Bool
myeqtest x y = if ⌊ x ≟ y ⌋ then true else false
or simply
myeqtest : ℕ -> ℕ -> Bool
myeqtest x y = ⌊ x ≟ y ⌋

Related

How to convince the Agda compiler that an expression terminates?

I'm learning Agda using Philip Wadler's Programming Language Foundations In Agda, and I can't figure out how to convince the compiler that a computation terminates.
I've got types for unary and binary naturals:
data ℕ : Set where
zero : ℕ
suc : ℕ → ℕ
data Bin : Set where
⟨⟩ : Bin
_O : Bin → Bin
_I : Bin → Bin
And I wrote a function to convert between the two representations (using some helpers):
-- try to count to a given power of two
--
-- to-count m t f n =
-- t (n - 2^m) if n >= 2^m
-- (f * 2^m) + n otherwise
to-count : ℕ → (ℕ → Bin) → Bin → ℕ → Bin
to-count zero t f zero = f
to-count zero t f (suc n) = t n
to-count (suc m) t f n = to-count m (to-count m t (f I)) (f O) n
-- keep trying to count bigger and bigger powers of two
to-next : ℕ → ℕ → Bin
to-next m = to-count m (to-next (suc m)) (⟨⟩ I)
to : ℕ → Bin
to = to-count zero (to-next zero) ⟨⟩
Later, when trying to prove that my conversion is faithful:
import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; cong)
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _≡⟨_⟩_; _∎)
_ : to zero ≡ ⟨⟩
_ = refl
_ : to (suc zero) ≡ ⟨⟩ I
_ = refl
The compiler complains that termination checking failed:
Checking Naturals (Naturals.agda).
Naturals.agda:23,1-24,48
Termination checking failed for the following functions:
to-next
Problematic calls:
to-next (suc m)
(at Naturals.agda:24,25-32)
Naturals.agda:37,5-9
to-next zero zero != ⟨⟩ I of type Bin
when checking that the expression refl has type
to (suc zero) ≡ (⟨⟩ I)
What are some strategies I can use to help convince the compiler that it terminates?
Using pragma is not how you need to convince the compiler that the function terminates.
The compiler indicated the problematic call: to-next (suc m) cannot be seen as unused in the cases you think, and obviously it creates a structurally bigger value than on input.
A way to deal with this problem is express the construction of Bin from ℕ differently.
inc-bin : Bin -> Bin
inc-bin ⟨⟩ = ⟨⟩ I
inc-bin (bb O) = bb I
inc-bin (bb I) = (inc-bin bb) O
to-bin-daft : ℕ -> Bin
to-bin-daft zero = b O
to-bin-daft (suc m) = inc-bin (to-bin-daft m)
This is "daft", as it literally increments Bin by one at a time, for every suc, but more complex algorithms involving, say, division by 2, require evidence that the result of division is smaller than the input.
Not sure if this is the most idiomatic solution, but I got it working using the TERMINATING pragma:
{-# TERMINATING #-}
to-next : ℕ → ℕ → Bin
to-next m = to-count m (to-next (suc m)) (⟨⟩ I)

How to inspect the value inside a product (Σ)?

I am trying to wrap my head around the Σ type by playing with a filterVec function, analogous to the filter function available for lists. See my implementation below:
-- Some imports we will need later
open import Data.Bool
open import Data.Nat
open import Data.Product
open import Data.Vec
-- The filterVec function
filterVec : {n : ℕ} -> (ℕ -> Bool) -> Vec ℕ n -> Σ ℕ (λ length → Vec ℕ length)
filterVec _ [] = 0 , []
filterVec f (x ∷ xs) with filterVec f xs
... | length , filtered = if f x then (suc length , x ∷ filtered) else (length , filtered)
Happy with my function, I decided to test it
dummyVec : Vec ℕ 5
dummyVec = 1 ∷ 2 ∷ 3 ∷ 4 ∷ 5 ∷ []
dummyFn : Vec ℕ 5
dummyFn with filterVec (λ _ → true) dummyVec
dummyFn | length , xs = {!!} -- I would like to return xs here, but Agda throws a type error
For some reason, Agda is unable to tell that length is 5, so it doesn't allow me to return xs. However, the code below does work:
open import Relation.Binary.PropositionalEquality
dummyProof : proj₁ (filterVec (λ _ → true) dummyVec) ≡ 5
dummyProof = refl
I am utterly confused by this behavior. In the case of dummyFn, Agda cannot tell that the length is 5, but in the case of dummyProof, Agda proves it without any problem.
What am I missing? How can I get dummyFn to work?
with binds a value to a name. If you want to compute, you can use let:
dummyFn′ : Vec ℕ 5
dummyFn′ = let length , xs = filterVec (λ _ → true) dummyVec
in xs
Let's look at the following example:
dummy : Set
dummy with 5
dummy | x = {!!}
Should the x magically reduce to 5 in the hole? No. You've given 5 another name — x, and those expressions are neither judgementally nor propositionally equal.
Now in your example:
dummyFn : Vec ℕ 5
dummyFn with filterVec (λ _ → true) dummyVec
dummyFn | length , xs = {!!}
You've given the length name to the length of xs. And it does not reduce to 5. It's a name. If you want both to give a name and to remember what the name is for, there is the inspect idiom for this:
dummyFn′′ : Vec ℕ 5
dummyFn′′ with filterVec (λ _ → true) dummyVec | inspect (filterVec (λ _ → true)) dummyVec
dummyFn′′ | length , xs | [ refl ] = xs

Irrelevant implicits: Why doesn't agda infer this proof?

Recently I made a type for finite sets in Agda with the following implementation:
open import Relation.Nullary
open import Relation.Nullary.Negation
open import Data.Empty
open import Data.Unit
open import Relation.Binary.PropositionalEquality
open import Data.Nat
suc-inj : (n m : ℕ) → (suc n) ≡ (suc m) → n ≡ m
suc-inj n .n refl = refl
record Eq (A : Set) : Set₁ where
constructor mkEqInst
field
_decide≡_ : (a b : A) → Dec (a ≡ b)
open Eq {{...}}
mutual
data FinSet (A : Set) {{_ : Eq A }} : Set where
ε : FinSet A
_&_ : (a : A) → (X : FinSet A) → .{ p : ¬ (a ∈ X)} → FinSet A
_∈_ : {A : Set} → {{p : Eq A}} → (a : A) → FinSet A → Set
a ∈ ε = ⊥
a ∈ (b & B) with (a decide≡ b)
... | yes _ = ⊤
... | no _ = a ∈ B
_∉_ : {A : Set} → {{p : Eq A}} → (a : A) → FinSet A → Set
_∉_ a X = ¬ (a ∈ X)
decide∈ : {A : Set} → {{_ : Eq A}} → (a : A) → (X : FinSet A) → Dec (a ∈ X)
decide∈ a ε = no (λ z → z)
decide∈ a (b & X) with (a decide≡ b)
decide∈ a (b & X) | yes _ = yes tt
... | no _ = decide∈ a X
decide∉ : {A : Set} → {{_ : Eq A}} → (a : A) → (X : FinSet A) → Dec (a ∉ X)
decide∉ a X = ¬? (decide∈ a X)
instance
eqℕ : Eq ℕ
eqℕ = mkEqInst decide
where decide : (a b : ℕ) → Dec (a ≡ b)
decide zero zero = yes refl
decide zero (suc b) = no (λ ())
decide (suc a) zero = no (λ ())
decide (suc a) (suc b) with (decide a b)
... | yes p = yes (cong suc p)
... | no p = no (λ x → p ((suc-inj a b) x))
However, when I test this type out with the following:
test : FinSet ℕ
test = _&_ zero ε
Agda for some reason can't infer the implicit argument of type ¬ ⊥! However, auto of course finds the proof of this trivial proposition: λ x → x : ¬ ⊥.
My question is this: Since I've marked the implicit proof as irrelevant, why can't Agda simply run auto to find the proof of ¬ ⊥ during type checking? Presumably, whenever filling in other implicit arguments, it might matter exactly what proof Agda finda, so it shouldn't just run auto, but if the proof has been marked irrelevant, like it my case, why can't Agda find a proof?
Note: I have a better implementation of this, where I implement ∉ directly, and Agda can find the relevant proof, but I want to understand in general why Agda can't automatically find these sorts of proofs for implicit arguments. Is there any way in the current implementation of Agda to get these "auto implicits" like I want here? Or is there some theoretical reason why this would be a bad idea?
There's no fundamental reason why irrelevant arguments couldn't be solved by proof search, however the fear is that in many cases it would be slow and/or not find a solution.
A more user-directed thing would be to allow the user to specify that a certain argument should be inferred using a specific tactic, but that has not been implemented either. In your case you would provide a tactic that tries to solve the goal with (\ x -> x).
If you give a more direct definition of ∉, then the implicit argument gets type ⊤ instead of ¬ ⊥. Agda can fill in arguments of type ⊤ automatically by eta-expansion, so your code just works:
open import Relation.Nullary
open import Relation.Nullary.Negation
open import Data.Empty
open import Data.Unit
open import Relation.Binary.PropositionalEquality
open import Data.Nat
suc-inj : (n m : ℕ) → (suc n) ≡ (suc m) → n ≡ m
suc-inj n .n refl = refl
record Eq (A : Set) : Set₁ where
constructor mkEqInst
field
_decide≡_ : (a b : A) → Dec (a ≡ b)
open Eq {{...}}
mutual
data FinSet (A : Set) {{_ : Eq A}} : Set where
ε : FinSet A
_&_ : (a : A) → (X : FinSet A) → .{p : (a ∉ X)} → FinSet A
_∉_ : {A : Set} → {{p : Eq A}} → (a : A) → FinSet A → Set
a ∉ ε = ⊤
a ∉ (b & X) with (a decide≡ b)
... | yes _ = ⊥
... | no _ = a ∉ X
decide∉ : {A : Set} → {{_ : Eq A}} → (a : A) → (X : FinSet A) → Dec (a ∉ X)
decide∉ a ε = yes tt
decide∉ a (b & X) with (a decide≡ b)
... | yes _ = no (λ z → z)
... | no _ = decide∉ a X
instance
eqℕ : Eq ℕ
eqℕ = mkEqInst decide
where decide : (a b : ℕ) → Dec (a ≡ b)
decide zero zero = yes refl
decide zero (suc b) = no (λ ())
decide (suc a) zero = no (λ ())
decide (suc a) (suc b) with (decide a b)
... | yes p = yes (cong suc p)
... | no p = no (λ x → p ((suc-inj a b) x))
test : FinSet ℕ
test = _&_ zero ε

How to define a singleton set?

Assume I have a value x : A and I want to define a set containing only x.
This is what I tried:
open import Data.Product
open import Relation.Binary.PropositionalEquality
-- Singleton x is the set that only contains x. Its values are tuples containing
-- a value of type A and a proof that this value is equal to x.
Singleton : ∀ {ℓ} {A : Set ℓ} → (x : A) → Set ℓ
Singleton {A = A} x = Σ[ y ∈ A ] (y ≡ x)
-- injection
singleton : ∀ {ℓ} {A : Set ℓ} → (x : A) → Singleton x
singleton x = x , refl
-- projection
fromSingleton : ∀ {ℓ} {A : Set ℓ} {x : A} → Singleton x → A
fromSingleton s = proj₁ s
Is there a better way to do it?
An example for why I want this: If you have a monoid over some set A, then you can form a category with A as the only object. To express that in Agda you need a way to write "the set containing only A".
I think this is a very good way to do it. Usually, when you want to create a "subset" of a type, it looks like:
postulate
A : Set
P : A → Set
record Subset : Set where
field
value : A
prop : P value
However, this might not be a subset in the sense that it can actually contain more elements than the original type. That is because prop might have more propositionally different values. For example:
open import Data.Nat
data ℕ-prop : ℕ → Set where
c1 : ∀ n → ℕ-prop n
c2 : ∀ n → ℕ-prop n
record ℕ-Subset : Set where
field
value : ℕ
prop : ℕ-prop value
And suddenly, the subset has twice as many elements as the original type. This example is a bit contrived, I agree, but imagine you had a subset relation on sets (sets from set theory). Something like this is actually fairly possible:
sub₁ : {1, 2} ⊆ {1, 2, 3, 4}
sub₁ = drop 3 (drop 4 same)
sub₂ : {1, 2} ⊆ {1, 2, 3, 4}
sub₂ = drop 4 (drop 3 same)
The usual approach to this problem is to use irrelevant arguments:
record Subset : Set where
field
value : A
.prop : P value
This means that two values of type Subset are equal if they have the same value, the prop field is irrelevant to the equality. And indeed:
record Subset : Set where
constructor sub
field
value : A
.prop : P value
prop-irr : ∀ {a b} {p : P a} {q : P b} →
a ≡ b → sub a p ≡ sub b q
prop-irr refl = refl
However, this is more of a guideline, because your representation doesn't suffer from this problem. This is because the implementation of pattern matching in Agda implies axiom K:
K : ∀ {a p} {A : Set a} (x : A) (P : x ≡ x → Set p) (h : x ≡ x) →
P refl → P h
K x P refl p = p
Well, this doesn't tell you much. Luckily, there's another property that is equivalent to axiom K:
uip : ∀ {a} {A : Set a} {x y : A} (p q : x ≡ y) → p ≡ q
uip refl refl = refl
This tells us that there's only one way in which two elements can be equal, namely refl (uip means uniqueness of identity proofs).
This means that when you use propositional equality to make a subset, you're getting a true subset.
Let's make this explicit:
isSingleton : ∀ {ℓ} → Set ℓ → Set _
isSingleton A = Σ[ x ∈ A ] (∀ y → x ≡ y)
isSingleton A expresses the fact that A contains only one element, up to propositonal equality. And indeed, Singleton x is a singleton:
Singleton-isSingleton : ∀ {ℓ} {A : Set ℓ} (x : A) →
isSingleton (Singleton x)
Singleton-isSingleton x = (x , refl) , λ {(.x , refl) → refl}
Interestingly, this also works without axiom K. If you put {-# OPTIONS --without-K #-} pragma at the top of your file, it will still compile.
You can define a record without projections:
record Singleton {α} {A : Set α} (x : A) : Set α where
fromSingleton : ∀ {α} {A : Set α} {x : A} -> Singleton x -> A
fromSingleton {x = x} _ = x
singleton : ∀ {α} {A : Set α} -> (x : A) -> Singleton x
singleton _ = _
Or equalently
record Singleton {α} {A : Set α} (x : A) : Set α where
fromSingleton = x
open Singleton public
singleton : ∀ {α} {A : Set α} -> (x : A) -> Singleton x
singleton _ = _
Now you can use it like this:
open import Relation.Binary.PropositionalEquality
open import Data.Nat
f : Singleton 5 -> ℕ
f x = fromSingleton x
test : f (singleton 5) ≡ 5
test = refl
test' : f _ ≡ 5
test' = refl
And this is rejected:
fail : f (singleton 4) ≡ 4
fail = ?
The error:
4 != 5 of type ℕ
when checking that the expression singleton 4 has type Singleton 5
It can be defined as an indexed datatype:
data Singleton {ℓ : _} {A : Set ℓ} : A -> Set where
singleton : (a : A) -> Singleton a
This is analogous to how propositional equality a ≡ b is indexed by two particular elements a and b, or how Vector X n is indexed by a particular n ∈ ℕ.

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