在Idris中,"Eq a"是一种类型,我可以为它提供一个值吗?

Phi*_*ell 5 typeclass idris

在下文中,example1是标准语法(如文档所述),Eq a作为约束.在example2,我Eq a直接指定为参数的类型,编译器接受它.但是,我不清楚我可以指定哪种类型的值.对于特定类型a,例如Nat,我假设以某种方式指定Eq Nat默认实现或某些其他命名实现的实现是有意义的.

%default total

example1: Eq a => (x : a) -> (y : a) -> Type
example1 {a} x y = ?example1_rhs

example1b: Eq a => (x : a) -> (y : a) -> Type
example1b {a} x y = x == y = True

example2: (a : Type) -> Eq a -> (x : a) -> (y : a) -> Type
example2 a eqa x y = ?example2_rhs

example2b: (a : Type) -> Eq a -> (x : a) -> (y : a) -> Type
example2b a eqa x y = x == y = True

eq_nat : Eq Nat
eq_nat = ?eq_nat_rhs

example_of_example2 : Type
example_of_example2 = example2 Nat eq_nat 3 3
Run Code Online (Sandbox Code Playgroud)

造成的漏洞:

- + Main.example1_rhs [P]
 `--                  a : Type
                      x : a
                      y : a
             constraint : Eq a
     --------------------------
      Main.example1_rhs : Type

- + Main.example2_rhs [P]
 `--                  a : Type
                    eqa : Eq a
                      x : a
                      y : a
     --------------------------
      Main.example2_rhs : Type

- + Main.eq_nat_rhs [P]
 `-- Eq Nat
Run Code Online (Sandbox Code Playgroud)

据我所知,我实际上不能example2b用作函数,除非我有办法为类型的第二个参数指定一个值Eq a.

在某些情况下,能够将接口约束应用于参数的值(而不是参数的类型)是非常有用的,所以我希望这是Idris的有效功能.

小智 6

您可以使用命名实现:

[eq_nat] Eq Nat where { ... }
...
example_of_example2 : Type
example_of_example2 = example2 Nat eq_nat 3 3
Run Code Online (Sandbox Code Playgroud)

命名实现的一个有用的应用是定义多个实现Monoid:

[PlusNatSemi] Semigroup Nat where
  (<+>) x y = x + y

[MultNatSemi] Semigroup Nat where
  (<+>) x y = x * y

[PlusNatMonoid] Monoid Nat using PlusNatSemi where
  neutral = 0

[MultNatMonoid] Monoid Nat using MultNatSemi where
  neutral = 1
Run Code Online (Sandbox Code Playgroud)

评论:获取默认实例

getEq : (a : Type) -> {auto inst : Eq a} -> Eq a
getEq a {inst} = inst
Run Code Online (Sandbox Code Playgroud)

然后你可以拥有你的默认实例:

getEq (List Nat) -- => implementation of Eq...
Run Code Online (Sandbox Code Playgroud)