Tree 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} ->

我通过学习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} -> 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  : ℕ