伊德里斯定义证明
Idris proof by definition
我会写函数
powApply : Nat -> (a -> a) -> a -> a
powApply Z f = id
powApply (S k) f = f . powApply k f
并简单证明:
powApplyZero : (f : _) -> (x : _) -> powApp Z f x = x
powApplyZero f x = Refl
到目前为止,还不错。现在,我尝试将此函数概括为使用负指数。当然,必须提供一个反函数:
import Data.ZZ
-- Two functions, f and g, with a proof that g is an inverse of f
data Invertible : Type -> Type -> Type where
MkInvertible : (f : a -> b) -> (g : b -> a) ->
((x : _) -> g (f x) = x) -> Invertible a b
powApplyI : ZZ -> Invertible a a -> a -> a
powApplyI (Pos Z) (MkInvertible f g x) = id
powApplyI (Pos (S k)) (MkInvertible f g x) =
f . powApplyI (Pos k) (MkInvertible f g x)
powApplyI (NegS Z) (MkInvertible f g x) = g
powApplyI (NegS (S k)) (MkInvertible f g x) =
g . powApplyI (NegS k) (MkInvertible f g x)
然后我尝试证明类似的说法:
powApplyIZero : (i : _) -> (x : _) -> powApplyI (Pos Z) i x = x
powApplyIZero i x = ?powApplyIZero_rhs
但是Idris拒绝评估powApplyI
的应用,留下?powApplyIZero_rhs
的类型为powApplyI (Pos 0) i x = x
(是的,Z
改为0
).我试过以非 pointsfree 风格编写 powApplyI
,并使用 %elim
修饰符(我不明白)定义我自己的 ZZ
,但这些都不起作用。为什么不通过检查 powApplyI
的第一个案例来处理证明?
伊德里斯版本:0.9.15.1
这里有一些东西:
powApplyNI : Nat -> Invertible a a -> a -> a
powApplyNI Z (MkInvertible f g x) = id
powApplyNI (S k) (MkInvertible f g x) = f . powApplyNI k (MkInvertible f g x)
powApplyNIZero : (i : _) -> (x : _) -> powApplyNI 0 i x = x
powApplyNIZero (MkInvertible f g y) x = Refl
powApplyZF : ZZ -> (a -> a) -> a -> a
powApplyZF (Pos Z) f = id
powApplyZF (Pos (S k)) f = f . powApplyZF (Pos k) f
powApplyZF (NegS Z) f = f
powApplyZF (NegS (S k)) f = f . powApplyZF (NegS k) f
powApplyZFZero : (f : _) -> (x : _) -> powApplyZF 0 f x = x
powApplyZFZero f x = ?powApplyZFZero_rhs
第一个证明很好,但是 ?powApplyZFZero_rhs
顽固地保留类型 powApplyZF (Pos 0) f x = x
。显然,ZZ
(或我对它的使用)存在一些问题。
powApplyI (Pos Z) i x
不会进一步减少,因为 i
不是弱头范式。
我没有 Idris 编译器,所以我用 Agda 重写了你的代码。非常相似:
open import Function
open import Relation.Binary.PropositionalEquality
open import Data.Nat
open import Data.Integer
data Invertible : Set -> Set -> Set where
MkInvertible : {a b : Set} (f : a -> b) -> (g : b -> a) ->
(∀ x -> g (f x) ≡ x) -> Invertible a b
powApplyI : {a : Set} -> ℤ -> Invertible a a -> a -> a
powApplyI ( + 0 ) (MkInvertible f g x) = id
powApplyI ( + suc k ) (MkInvertible f g x) = f ∘ powApplyI ( + k ) (MkInvertible f g x)
powApplyI -[1+ 0 ] (MkInvertible f g x) = g
powApplyI -[1+ suc k ] (MkInvertible f g x) = g ∘ powApplyI -[1+ k ] (MkInvertible f g x)
现在您可以将 powApplyIZero
定义为
powApplyIZero : {a : Set} (i : Invertible a a) -> ∀ x -> powApplyI (+ 0) i x ≡ x
powApplyIZero (MkInvertible _ _ _) _ = refl
i
上的模式匹配导致统一,powApplyI (+ 0) i x
被 powApplyI (+ 0) i (MkInvertible _ _ _)
取代,因此 powApplyI
可以进一步进行。
或者你可以明确地这样写:
powApplyIZero : {a : Set} (f : a -> a) (g : a -> a) (p : ∀ x -> g (f x) ≡ x)
-> ∀ x -> powApplyI (+ 0) (MkInvertible f g p) x ≡ x
powApplyIZero _ _ _ _ = refl
问题:根据 Idris 的说法,powApplyI
并不是完全可以证明的。 Idris 的完整性检查器依赖于能够将参数减少到结构上更小的形式,并且对于原始 ZZ
s,这是行不通的。
答案是将递归委托给普通的旧powApply
(已证明总数):
total
powApplyI : ZZ -> a <~ a -> a -> a
powApplyI (Pos k) (MkInvertible f g x) = powApply k f
powApplyI (NegS k) (MkInvertible f g x) = powApply (S k) g
然后,通过 i
上的案例拆分,powApplyIZero
被证明是微不足道的。
感谢来自 #idris IRC 频道的 Melvar。
我会写函数
powApply : Nat -> (a -> a) -> a -> a
powApply Z f = id
powApply (S k) f = f . powApply k f
并简单证明:
powApplyZero : (f : _) -> (x : _) -> powApp Z f x = x
powApplyZero f x = Refl
到目前为止,还不错。现在,我尝试将此函数概括为使用负指数。当然,必须提供一个反函数:
import Data.ZZ
-- Two functions, f and g, with a proof that g is an inverse of f
data Invertible : Type -> Type -> Type where
MkInvertible : (f : a -> b) -> (g : b -> a) ->
((x : _) -> g (f x) = x) -> Invertible a b
powApplyI : ZZ -> Invertible a a -> a -> a
powApplyI (Pos Z) (MkInvertible f g x) = id
powApplyI (Pos (S k)) (MkInvertible f g x) =
f . powApplyI (Pos k) (MkInvertible f g x)
powApplyI (NegS Z) (MkInvertible f g x) = g
powApplyI (NegS (S k)) (MkInvertible f g x) =
g . powApplyI (NegS k) (MkInvertible f g x)
然后我尝试证明类似的说法:
powApplyIZero : (i : _) -> (x : _) -> powApplyI (Pos Z) i x = x
powApplyIZero i x = ?powApplyIZero_rhs
但是Idris拒绝评估powApplyI
的应用,留下?powApplyIZero_rhs
的类型为powApplyI (Pos 0) i x = x
(是的,Z
改为0
).我试过以非 pointsfree 风格编写 powApplyI
,并使用 %elim
修饰符(我不明白)定义我自己的 ZZ
,但这些都不起作用。为什么不通过检查 powApplyI
的第一个案例来处理证明?
伊德里斯版本:0.9.15.1
这里有一些东西:
powApplyNI : Nat -> Invertible a a -> a -> a
powApplyNI Z (MkInvertible f g x) = id
powApplyNI (S k) (MkInvertible f g x) = f . powApplyNI k (MkInvertible f g x)
powApplyNIZero : (i : _) -> (x : _) -> powApplyNI 0 i x = x
powApplyNIZero (MkInvertible f g y) x = Refl
powApplyZF : ZZ -> (a -> a) -> a -> a
powApplyZF (Pos Z) f = id
powApplyZF (Pos (S k)) f = f . powApplyZF (Pos k) f
powApplyZF (NegS Z) f = f
powApplyZF (NegS (S k)) f = f . powApplyZF (NegS k) f
powApplyZFZero : (f : _) -> (x : _) -> powApplyZF 0 f x = x
powApplyZFZero f x = ?powApplyZFZero_rhs
第一个证明很好,但是 ?powApplyZFZero_rhs
顽固地保留类型 powApplyZF (Pos 0) f x = x
。显然,ZZ
(或我对它的使用)存在一些问题。
powApplyI (Pos Z) i x
不会进一步减少,因为 i
不是弱头范式。
我没有 Idris 编译器,所以我用 Agda 重写了你的代码。非常相似:
open import Function
open import Relation.Binary.PropositionalEquality
open import Data.Nat
open import Data.Integer
data Invertible : Set -> Set -> Set where
MkInvertible : {a b : Set} (f : a -> b) -> (g : b -> a) ->
(∀ x -> g (f x) ≡ x) -> Invertible a b
powApplyI : {a : Set} -> ℤ -> Invertible a a -> a -> a
powApplyI ( + 0 ) (MkInvertible f g x) = id
powApplyI ( + suc k ) (MkInvertible f g x) = f ∘ powApplyI ( + k ) (MkInvertible f g x)
powApplyI -[1+ 0 ] (MkInvertible f g x) = g
powApplyI -[1+ suc k ] (MkInvertible f g x) = g ∘ powApplyI -[1+ k ] (MkInvertible f g x)
现在您可以将 powApplyIZero
定义为
powApplyIZero : {a : Set} (i : Invertible a a) -> ∀ x -> powApplyI (+ 0) i x ≡ x
powApplyIZero (MkInvertible _ _ _) _ = refl
i
上的模式匹配导致统一,powApplyI (+ 0) i x
被 powApplyI (+ 0) i (MkInvertible _ _ _)
取代,因此 powApplyI
可以进一步进行。
或者你可以明确地这样写:
powApplyIZero : {a : Set} (f : a -> a) (g : a -> a) (p : ∀ x -> g (f x) ≡ x)
-> ∀ x -> powApplyI (+ 0) (MkInvertible f g p) x ≡ x
powApplyIZero _ _ _ _ = refl
问题:根据 Idris 的说法,powApplyI
并不是完全可以证明的。 Idris 的完整性检查器依赖于能够将参数减少到结构上更小的形式,并且对于原始 ZZ
s,这是行不通的。
答案是将递归委托给普通的旧powApply
(已证明总数):
total
powApplyI : ZZ -> a <~ a -> a -> a
powApplyI (Pos k) (MkInvertible f g x) = powApply k f
powApplyI (NegS k) (MkInvertible f g x) = powApply (S k) g
然后,通过 i
上的案例拆分,powApplyIZero
被证明是微不足道的。
感谢来自 #idris IRC 频道的 Melvar。