我想定义一个类型构造函数,它体现了使用类型包装器通过投影到具有函数t1
的域类型t2
来定义域类型p
上的相等性的概念。
以下具体示例有效,其中t1
= ABC
,t2
= Nat
和p
是函数abc_2_nat
:
%default total
data ABC = A | B | C
abc_2_nat : ABC -> Nat
abc_2_nat A = 1
abc_2_nat B = 1
abc_2_nat C = 2
data Projected_abc : Type where
Project_abc : ABC -> Projected_abc
Projected_abc_equals : Projected_abc -> Projected_abc -> Bool
Projected_abc_equals (Project_abc x) (Project_abc y) = abc_2_nat x == abc_2_nat y
Eq Projected_abc where
(==) = Projected_abc_equals
但是,当我试图概括如下:
data Projected : t1 -> t2 -> (p: t1 -> t2) -> Type
where Project : t1 -> Projected t1 t2 p
Projected_equals : Projected t1 t2 p -> Projected t1 t2 p -> Bool
Projected_equals (Project x) (Project y) = ?hole
我得到了这个洞:
- + Main.hole [P]
`-- phTy : Type
t2 : phTy
p : Type -> phTy
t1 : Type
x : t1
y : t1
--------------------------
Main.hole : Bool
这不起作用,因为它无法识别p
属于t1->t2
类型(这就是我想要的)。
我怀疑我要求将投影函数作为类型构造函数的参数提供太多,并且在某个函数的定义范围内以某种方式提供了投影函数,该函数的参数属于构造类型。 / p>
有什么方法可以让它发挥作用吗?
答案 0 :(得分:4)
可以做到。你Projected
概括不够准确。您应指定t1
和t2
的类型。像这样:
data Projected : (t1: Type) -> (t2: Type) -> (p: t1 -> t2) -> Type where
Project : t1 -> Projected t1 t2 p
如果没有这个,Idris编译器无法准确猜出t1
和t2
是什么类型的东西。还有一点需要注意:要通过比较t1
域的投影来比较t2
类型的值,您应该确保可以比较t2
类型的值。因此,一般投影平等看起来像这样:
projected_equals : Eq t2 => Projected t1 t2 p -> Projected t1 t2 p -> Bool
projected_equals {p} (Project x) (Project y) = p x == p y
你可以为它编写Eq
个实例!
Eq t2 => Eq (Projected t1 t2 p) where
(==) = projected_equals
它也有效。所以如果你定义这样的东西:
data ABC = A | B | C
abc_2_nat : ABC -> Nat
abc_2_nat A = 1
abc_2_nat B = 1
abc_2_nat C = 2
您可以使用abc_2_nat
投影来实现相应的投影机:
abcNatProjector : ABC -> Projected ABC Nat Main.abc_2_nat
abcNatProjector abc = Project abc
我必须使用Main.abc_2_nat
来解决歧义,否则abc_2_nat
可以是任何隐式类型参数。伊德里斯无力猜测你想要什么。很高兴,编译器帮助我发出这个警告:
Eq.idr:13:37-46:WARNING: abc_2_nat is bound as an implicit
Did you mean to refer to Main.abc_2_nat?
现在你可以在REPL中检查它是否有效!
λΠ> abcNatProjector A == abcNatProjector B
True : Bool
λΠ> abcNatProjector A == abcNatProjector C
False : Bool
加分:
如果您将abcNatProjector
标记为implicit
功能,请执行以下操作:
implicit
abcNatProjector : ABC -> Projected ABC Nat Main.abc_2_nat
abcNatProjector abc = Project abc
您可以定义一些奇特的运算符
infixr 5 ==^
(==^) : Eq t2 => Projected t1 t2 p -> Projected t1 t2 p -> Bool
(==^) = projected_equals
将ABC
类型的值与其进行比较,而不明确使用abcNatProjector
。
λΠ> A ==^ B
True : Bool
λΠ> A ==^ C
False : Bool