Agda's mixiture of records and the instance
keyword give us behaviour similar to that of Haskell's typeclasses. Moreover, ignoring the instance
keyword, we can have more than one instance for the same type --- something we cannot do in Haskell.
I am at a point where I need Haskell's one-instance only requirement, but in Agda. Is there an compiler option or some trick/heuristic to enforce this?
Right now the approach I am taking is,
record Yo (n : ℕ) : Set where
field
sem : (some interesting property involving n)
open Yo {{...}}
postulate UniqueYo: ∀ {n} (p q : Yo n) → p ≡ q
However, whenever I actually use UniqueYo
the lack of computation leaves my goals littered with things like ...| UniqueYo p p
where I'd prefer ...| refl
or a full rewrite into normal form instead.
Any help is appreciated!
With newer versions of Agda you could use the Prop
universe to get definitional uniqueness of a type:
{-# OPTIONS --prop #-}
module UniquenessUsingProp where
open import Data.Nat.Base
open import Relation.Binary.PropositionalEquality
-- Convert a Set to a Prop. This could be avoided if e.g.
-- we defined > as a Prop (like in the example in the docs
-- linked above)
data Squash {ℓ} (A : Set ℓ) : Prop ℓ where
squash : A → Squash A
-- record Yo (n : ℕ) : Prop where -- Both variants works
record Yo (n : ℕ) : Set where
field
sem : Squash (n + 1 > n * 2)
-- Since `Yo n` is a Prop and not a set, it can't be the
-- direct argument of ≡. This is not a problem since
-- it's definitionally equal anyways.
UniqueYo : ∀ {n} (P : Yo n → Set) (p q : Yo n) → P p ≡ P q
UniqueYo P p q = refl
Another alternative that produces similar results is using proof irrelevant record fields:
module UniqunessUsingProofIrrelevance where
open import Data.Nat.Base
open import Relation.Binary.PropositionalEquality
record Yo (n : ℕ) : Set where
field
.sem : n + 1 > n * 2
open Yo {{...}}
UniqueYo : ∀ {n} (p q : Yo n) → p ≡ q
UniqueYo p q = refl
In both cases, actually using the value in Yo can be difficult, since you need to convince Agda that your code does not depend on the concrete value in sem
, e.g. by only using absurd pattern matches on it or by producing values in Prop
or respectively, providing it as an argument to irrelevant functions.