如何在Idris中定义函数的属性作为自己的逆?

时间:2017-04-16 01:48:15

标签: idris

我希望能够说,对于具有签名t-> t的f的函数,对于t中的所有x,f(f(x))= x。

当我运行时:

%default total

-- The type of parity values - either Even or Odd
data Parity = Even | Odd

-- Even is the opposite of Odd and Odd is the opposite of Even
opposite: Parity -> Parity
opposite Even = Odd
opposite Odd  = Even

-- The 'opposite' function is it's own inverse
opposite_its_own_inverse : (p : Parity) -> opposite (opposite p) = p
opposite_its_own_inverse Even = Refl
opposite_its_own_inverse Odd  = Refl

-- abstraction of being one's own inverse

IsItsOwnInverse : {t : Type} -> (f: t->t) -> Type
IsItsOwnInverse {t} f = (x: t) -> f (f x) = x

opposite_IsItsOwnInverse : IsItsOwnInverse {t=Parity} opposite
opposite_IsItsOwnInverse = opposite_its_own_inverse

我收到此错误消息:

- + Errors (1)
 `-- own_inverse_example.idr line 22 col 25:
     When checking right hand side of opposite_IsItsOwnInverse with expected type
             IsItsOwnInverse opposite

     Type mismatch between
             (p : Parity) ->
             opposite (opposite p) = p (Type of opposite_its_own_inverse)
     and
             (x : Parity) -> opposite (opposite x) = x (Expected type)

     Specifically:
             Type mismatch between
                     opposite (opposite v0)
             and
                     opposite (opposite v0)

我做错了什么,还是只是一个错误?

如果我用'?hole'替换最后一个'opposite_its_own_inverse',我得到:

Holes

This buffer displays the unsolved holes from the currently-loaded code. Press
the [P] buttons to solve the holes interactively in the prover.

- + Main.hole [P]
 `--   opposite : Parity -> Parity
     -------------------------------------------------------
      Main.hole : (x : Parity) -> opposite (opposite x) = x

1 个答案:

答案 0 :(得分:4)

此属性的名称是involution。你对这个属性的类型非常好,但我喜欢这样写:

Involution : (t -> t) -> t -> Type
Involution f x = f (f x) = x

opposite_IsItsOwnInverse的第一个问题是您尚未完全应用Involution,因此您还没有获得类型。您还需要应用Parity,以便Involution提供Type,如下所示:

opposite_IsItsOwnInverse : Involution opposite p

p是一个隐含的参数。隐式参数由类型签名中的小写标识符隐式创建。这就像写作:

opposite_IsItsOwnInverse : {p : Parity} -> Involution opposite p

但这会导致签名的另一个问题 - opposite也是小写的,因此它被视为隐式参数! (这就是为什么你得到令人困惑的错误信息,Idris创建了另一个名为opposite变量。你在这里有2个可能的解决方案:限定标识符,或者使用以大写字母开头的标识符信。

我假设您正在编写的模块使用默认名称Main。最终类型签名如下:

opposite_IsItsOwnInverse : Involution Main.opposite p

实现将只使用隐式参数并将其提供给您已编写的函数:

opposite_IsItsOwnInverse {p} = opposite_its_own_inverse p