Idris - 枚举类型的 Eq
Idris - Eq for enumerated type
假设我有一个枚举类型
data MyType
= One
| Two
| Three
...
| Ten
我想为它实现 Eq
接口。我可以这样做
Eq MyType where
One == One = True
Two == Two = True
...
Ten == Ten = True
_ == _ = False
但这看起来很乏味。
在 Idris 中是否有更好更准确的方法来做到这一点?
您正在寻找 instance/implementation 为 Idris 推导。
有一个 "Derive all the instances" 项目,它似乎有一个 working solution for Eq(请参阅文件末尾的示例)。但是,将来可能不会维护它。
还有 a newer project in the works 也跨越 Eq
,但仍需完成。
可以直接在 Idris 中定义 EnumeratedType
的概念。基本思想是在 MyType
和 Fin 10
之间定义一个 1-1 映射。一旦你完成了在每个方向定义映射的稍微乏味的工作(values
和 toFin
,用 values_match_toFin
验证它们彼此一致),那么你可以定义东西喜欢 Eq
通过更结构化的 Fin
类型不那么乏味。
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
假设我有一个枚举类型
data MyType
= One
| Two
| Three
...
| Ten
我想为它实现 Eq
接口。我可以这样做
Eq MyType where
One == One = True
Two == Two = True
...
Ten == Ten = True
_ == _ = False
但这看起来很乏味。
在 Idris 中是否有更好更准确的方法来做到这一点?
您正在寻找 instance/implementation 为 Idris 推导。
有一个 "Derive all the instances" 项目,它似乎有一个 working solution for Eq(请参阅文件末尾的示例)。但是,将来可能不会维护它。
还有 a newer project in the works 也跨越 Eq
,但仍需完成。
可以直接在 Idris 中定义 EnumeratedType
的概念。基本思想是在 MyType
和 Fin 10
之间定义一个 1-1 映射。一旦你完成了在每个方向定义映射的稍微乏味的工作(values
和 toFin
,用 values_match_toFin
验证它们彼此一致),那么你可以定义东西喜欢 Eq
通过更结构化的 Fin
类型不那么乏味。
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