在类型类中使用TypeClass实例

时间:2017-06-19 19:39:04

标签: typeclass coq

我试图定义一个类型类的两个实例,其中一个将使用另一个实例。但是,除非我将函数的名称绑定到第二个定义之外,否则Coq无法确定它应该使用bexp中的类型类实例(请查看脏黑客的注释)。有没有办法避免在Coq中出现这种黑客行为?

Class Compilable ( A : Type ) := { compile : A -> bool }.

Inductive cexp : Type :=
| CAnd :  cexp -> cexp -> cexp
| COr  :  cexp -> cexp -> cexp
| CProp : bexp -> cexp.  


Instance: Compilable bexp :=
  { compile :=
      fix compile b :=
          match b with
          (* elided *)
          end
  }.

Definition compile2 := compile.

Instance: Compilable cexp :=
  { compile :=
      fix compile c :=
        match c with
        | CAnd x y => (compile x) && (compile y)
        | COr x y => (compile x) || (compile y)
        | CProp e => (compile2 e) (* <-- dirty hack *)
        end
  }.

1 个答案:

答案 0 :(得分:3)

如果我们将compile替换为其他名称(rec),则可以修复此问题:

Instance: Compilable cexp :=
  { compile :=
      fix rec c :=
        match c with
        | CAnd x y => (rec x) && (rec y)
        | COr x y => (rec x) || (rec y)
        | CProp e => (compile e)
        end
  }.

this comment中,OP指出Haskell很容易处理这种情况。要理解Coq不这样做的原因,让我们来看看compile的类型:

About compile.
compile : forall A : Type, Compilable A -> A -> bool
     

参数ACompilable是隐式和最大插入的

我们可以看到Coq更明确地说明类型类是如何工作的。当您调用compile e Coq时插​​入占位符代表隐含参数,例如@compile _ _ e(请参阅these slides,第21-25页以获取更多详细信息)。但是使用fix compile c,您会隐藏前一个绑定,因此会出现类型错误。