Tree Agda中的静态平衡树
我通过学习Agda来自学依赖类型 这是一个二叉树的类型,通过大小来平衡Tree Agda中的静态平衡树,tree,agda,dependent-type,Tree,Agda,Dependent Type,我通过学习Agda来自学依赖类型 这是一个二叉树的类型,通过大小来平衡 open import Data.Nat open import Data.Nat.Properties.Simple data T (A : Set) : ℕ -> Set where empty : T A 0 leaf : A -> T A 1 bal : ∀ {n} -> T A n -> T A n -> T A (n + n) heavyL : ∀ {n} ->
open import Data.Nat
open import Data.Nat.Properties.Simple
data T (A : Set) : ℕ -> Set where
empty : T A 0
leaf : A -> T A 1
bal : ∀ {n} -> T A n -> T A n -> T A (n + n)
heavyL : ∀ {n} -> T A (suc n) -> T A n -> T A (suc (n + n))
树可以是完全平衡的(bal
),或者左子树可以包含比右子树多一个元素(heavyL
)。(在这种情况下,下一次插入将进入右子树。)其思想是插入将在树的左半部和右半部之间翻转,有效地(决定性地)洗牌输入列表
我无法定义insert
typecheck:
insert : ∀ {A n} -> A -> T A n -> T A (suc n)
insert x empty = leaf x
insert x (leaf y) = bal (leaf x) (leaf y)
insert x (bal l r) = heavyL (insert x l) r
insert x (heavyL l r) = bal l (insert x r)
Agda拒绝将bal(插入x r)
作为heavyL
案例的右侧:
.n + suc .n != suc (.n + .n) of type ℕ
when checking that the expression bal l (insert x r) has type
T .A (suc (suc (.n + .n)))
我试图用证据来修补我的定义
insert x (heavyL {n} l r) rewrite +-suc n n = bal l (insert x r)
。。。但是我收到了同样的错误信息。(我是否误解了重写的作用?)
我还尝试在相同的证明假设下转换大小相等的树:
convertT : ∀ {n m A} -> T A (n + suc m) -> T A (suc (n + m))
convertT {n} {m} t rewrite +-suc n m = t
insert x (heavyL {n} l r) rewrite +-suc n n = bal (convertT l) (convertT (insert x r))
Agda接受这一可能性,但以黄色突出显示方程式。我想我需要明确给出传递给bal
构造函数的两个子树的大小:
insert x (heavyL {n} l r) rewrite +-suc n n = bal {n = suc n} (convertT l) (convertT (insert x r))
但是现在我又收到了同样的错误消息
n + suc n != suc (n + n) of type ℕ
when checking that the expression
bal {n = suc n} (convertT l) (convertT (insert x r)) has type
T .A (suc (suc (n + n)))
我没有主意了。我肯定我犯了一个愚蠢的错误。我做错了什么?我需要做什么才能定义
插入
类型检查?您的重写
尝试几乎奏效,但它使用的相等性是错误的方向。要使其朝正确的方向工作,可以将其翻转:
open import Relation.Binary.PropositionalEquality
-- ...
insert x (heavyL {n} l r) rewrite sym (+-suc n n) = bal l (insert x r)
或将与
子句一起使用:
insert x (heavyL {n} l r) with bal l (insert x r)
... | t rewrite +-suc n n = t
另一种可能是自己在右侧进行替换:
open import Relation.Binary.PropositionalEquality
-- ...
insert x (heavyL {n} l r) = subst (T _) (+-suc (suc n) n) (bal l (insert x r))
您只需朝另一个方向重写:
open import Relation.Binary.PropositionalEquality
insert : ∀ {A n} -> A -> T A n -> T A (suc n)
insert x empty = leaf x
insert x (leaf y) = bal (leaf y) (leaf y)
insert x (bal l r) = heavyL (insert x l) r
insert x (heavyL {n} l r) rewrite sym (+-suc n n) = bal l (insert x r)
您可以使用Agda的大孔机械来了解发生了什么:
insert x (heavyL {n} l r) = {!!}
在键入检查并将光标放在{!!}
内后,您可以键入C-C-,
并获取
Goal: T .A (suc (suc (n + n)))
————————————————————————————————————————————————————————————
r : T .A n
l : T .A (suc n)
n : ℕ
x : .A
.A : Set
将ball(插入x r)
放入孔中并键入C-C-。
您将获得
Goal: T .A (suc (suc (n + n)))
Have: T .A (suc (n + suc n))
————————————————————————————————————————————————————————————
r : T .A n
l : T .A (suc n)
n : ℕ
x : .A
.A : Set
因此存在不匹配<代码>重写修复它:
insert x (heavyL {n} l r) rewrite sym (+-suc n n) = {!bal l (insert x r)!}
现在输入C-C-。
(在检查后)给出
您可以通过在孔中键入C-C-r
来完成定义
Agda承认这是一种可能性,但强调了
黄色
Agda无法从
n+suc m
推断n
和m
,因为n
上存在模式匹配。Agda邮件列表中有一个关于隐式参数的问题。谢谢!真不敢相信我竟然没有想到sym
。我也不知道C-C-。
来看看你有什么。
Goal: T .A (suc (n + suc n))
Have: T .A (suc (n + suc n))
————————————————————————————————————————————————————————————
r : T .A n
l : T .A (suc n)
x : .A
.A : Set
n : ℕ