Suppose I have an enumerated type like
data MyType
= One
| Two
| Three
...
| Ten
and I would like to implement the Eq
interface for it. I could do it as follows
Eq MyType where
One == One = True
Two == Two = True
...
Ten == Ten = True
_ == _ = False
but this looks tedious.
Is there a better and more coincise way to do this in Idris?
You're looking for instance/implementation deriving for Idris.
There's a "Derive all the instances" project, which seems to have a working solution for Eq (see examples at the end of the file). However, it'll probably not be maintained in the future.
There's a newer project in the works which also spans Eq
, but still has to be completed.
It is possible to define the concept of an EnumeratedType
directly in Idris. The basic idea is to define a 1-1 mapping between MyType
and Fin 10
. Once you've done the slightly tedious work of defining the mapping in each direction (values
and toFin
, with values_match_toFin
verifying that they are consistent with each other), then you can define things like Eq
less tediously via the more structured Fin
type.
import Data.Vect
%default total
range : (n : Nat) -> Vect n (Fin n)
range Z = []
range (S k) = (FZ :: (map FS $ range k))
interface EnumeratedType (t : Type) (size : Nat) | t where
values : Vect size t
toFin : t -> Fin size
values_match_toFin : map toFin values = range size
fromFin : (EnumeratedType t size) => Fin size -> t
fromFin x = index x values
data MyType = One | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten
EnumeratedType MyType 10 where
values = [One, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten]
toFin One = 0
toFin Two = 1
toFin Three = 2
toFin Four = 3
toFin Five = 4
toFin Six = 5
toFin Seven = 6
toFin Eight = 7
toFin Nine = 8
toFin Ten = 9
values_match_toFin = Refl
eq_from_fin : (EnumeratedType t size) => t -> t -> Bool
eq_from_fin x y = toFin x == toFin y
Eq MyType where
(==) = eq_from_fin
Three_eq_Three : Three == Three = True
Three_eq_Three = Refl
Four_not_eq_Seven : Four == Seven = False
Four_not_eq_Seven = 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