Idris-通常为接口创建可确定的属性/证明

时间:2018-06-28 21:40:33

标签: idris

是否可以为Idris中的接口创建可确定的属性,以供在接口内部使用?

例如-假设我们有一个简单的接口Foo和一个数据类型 FooTypeEmpty表示给定foo对象为“空”(定义为“由两个零索引”)的语句:

interface Foo (foo : Nat -> Nat -> Type -> Type) where
    mkEmpty : foo 0 0 a
    isEmpty : (f : foo n m a) -> Bool

data FooTypeEmpty : (Foo foo) => foo n m a -> Type where
    MkFooTypeEmpty : (Foo foo) => (f : foo 0 0 a) -> FooTypeEmpty f 

是否可以将isEmpty方法赋予以下类型?:

isEmpty : (f : foo n m a) -> Dec (FooTypeEmpty f)

也就是说,使用FooTypeEmpty以便isEmpty返回证明(或矛盾)给定的foo对象为“空”?

我尝试了使用互斥块,但这不会进行类型检查:

mutual
    interface Foo (foo : Nat -> Nat -> Type -> Type) where
        mkEmpty : foo 0 0 a
        isEmpty : (f : foo n m a) -> Dec (FooTypeEmpty f)

    data FooTypeEmpty : (Foo foo) => foo n m a -> Type where
        FTE : (Foo foo) => (f : foo 0 0 a) -> FooTypeEmpty f

更笼统地说:是否有可能在所有实现中都有效/必需的接口方法中加入证明?

1 个答案:

答案 0 :(得分:2)

您无法访问他定义中正在构造的FooisEmpty会需要它。接口只是花哨的数据构造函数,因此您的接口大致等同于:

MkFoo : (foo : Nat -> Nat -> Type -> Type) ->
        (mkEmpty : foo 0 0 a) ->
        (isEmpty : ((f : foo n m a) -> 
            Dec (FooTypeEmpty f {Foo interface=MkFoo foo mkEmpty isEmpty})) ->
        Foo foo

由于在MkFoo中对isEmpty的自我引用,Foo并不是严格意义上的肯定,因此也不是完全肯定的。

因此,您必须事先定义证明类型。只需使用相同类型的参数:

data FooTypeEmpty : {foo : Nat -> Nat -> Type -> Type} -> 
                    foo n m a -> Type where
    FTE : {foo : Nat -> Nat -> Type -> Type} ->
          (f : foo 0 0 a) -> FooTypeEmpty f

interface Foo (foo : Nat -> Nat -> Type -> Type) where
    mkEmpty : foo 0 0 a
    isEmpty : (f : foo n m a) -> Dec (FooTypeEmpty f)

data Bar : Nat -> Nat -> Type -> Type where
  Empty : Bar 0 0 a

Foo Bar where
  mkEmpty = Empty
  isEmpty = \Empty => Yes (FTE Empty)

如果您想证明有关给接口的功能的某些信息,只需将它们作为额外的参数(在此处mkEmpty):

data FooTypeEmpty : {foo : Nat -> Nat -> Type -> Type} -> 
                    {mkEmpty : foo 0 0 a} ->
                    foo n m a -> Type where
    FTE : {foo : Nat -> Nat -> Type -> Type} ->
          {mkEmpty : foo 0 0 a} ->
          FooTypeEmpty mkEmpty

interface Foo (foo : Nat -> Nat -> Type -> Type) where
    mkEmpty : foo 0 0 a
    isEmpty : (f : foo n m a) -> Dec (FooTypeEmpty {mkEmpty} f)

data Bar : Nat -> Nat -> Type -> Type where
  Empty : Bar 0 0 a

Foo Bar where
  mkEmpty = Empty
  isEmpty = \Empty => Yes FTE

您不能赋予FooTypeEmpty的唯一功能是使用证明本身的功能。