我可以在Idris中定义x == y = p(x)== p(y)的一般概念吗?

时间:2017-05-15 08:58:21

标签: idris

我想定义一个类型构造函数,它体现了使用类型包装器通过投影到具有函数t1的域类型t2来定义域类型p上的相等性的概念。

以下具体示例有效,其中t1 = ABCt2 = Natp是函数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>

有什么方法可以让它发挥作用吗?

1 个答案:

答案 0 :(得分:4)

可以做到。你Projected概括不够准确。您应指定t1t2的类型。像这样:

data Projected : (t1: Type) -> (t2: Type) -> (p: t1 -> t2) -> Type where
    Project : t1 -> Projected t1 t2 p

如果没有这个,Idris编译器无法准确猜出t1t2是什么类型的东西。还有一点需要注意:要通过比较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