在下文中,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)