Idris - 枚举类型的Eq

时间:2017-11-23 23:19:08

标签: types idris

假设我有一个类似

的枚举类型
data MyType
    = One
    | Two
    | Three
    ...
    | Ten

我想为它实现Eq接口。我可以这样做

Eq MyType where
    One == One = True
    Two == Two = True
    ...
    Ten == Ten = True
    _ == _ = False

但这看起来很乏味。

在伊德里斯这样做有更好,更巧合的方法吗?

2 个答案:

答案 0 :(得分:5)

您正在寻找Idris的实例/实现派生。

有一个“派生所有实例”项目,似乎有working solution for Eq(参见文件末尾的示例)。但是,将来可能不会维护它。 a newer project in the works也跨越Eq,但仍需完成。

答案 1 :(得分:2)

可以直接在Idris中定义EnumeratedType的概念。基本思想是在MyTypeFin 10之间定义1-1映射。一旦完成了在每个方向(valuestoFin定义映射的轻微繁琐工作,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