假设我有一个类似
的枚举类型data MyType
= One
| Two
| Three
...
| Ten
我想为它实现Eq
接口。我可以这样做
Eq MyType where
One == One = True
Two == Two = True
...
Ten == Ten = True
_ == _ = False
但这看起来很乏味。
在伊德里斯这样做有更好,更巧合的方法吗?
答案 0 :(得分:5)
您正在寻找Idris的实例/实现派生。
有一个“派生所有实例”项目,似乎有working solution for Eq(参见文件末尾的示例)。但是,将来可能不会维护它。
a newer project in the works也跨越Eq
,但仍需完成。
答案 1 :(得分:2)
可以直接在Idris中定义EnumeratedType
的概念。基本思想是在MyType
和Fin 10
之间定义1-1映射。一旦完成了在每个方向(values
和toFin
定义映射的轻微繁琐工作,values_match_toFin
验证它们彼此一致),那么您可以定义事物比较Eq
类型的Fin
更为繁琐。{/ 1>
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