You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Agda递归证明问题:索引操作一致性证明遇类型错误

Agda中Positive索引树get/set独立性证明的类型错误解决

问题背景

我在Agda中定义了递归数据类型Positive,用于为Tree类型建立索引。目标是证明:当对索引q执行set操作时,不会影响对另一索引p的get操作结果(要求i ≢ j)。

代码与遇到的错误

1. gso证明函数的递归错误

编写的证明函数框架:

gso : {A : Set} -> ∀ (i j : Positive) (t : Tree A) (v : A) → ((i ≡ j) → ⊥) → get i (set j v t) ≡ get i t
gso (xI p) (xI p) t v = ? 
gso (xO p) (xO p) t v = ?
gso p q t v = ? -- 此分支可正常工作

尝试拆分Tree分支递归调用时:

gso (xI p) (xI q) (Nodes (node001 t)) v neq = gso p q (Nodes t) v neq

出现类型错误:

p != (xI p) of type Positive
when checking that the expression neq has type p ≡ q → ⊥

2. 辅助证明函数的递归错误

尝试编写证明xI构造子保持相等性的辅助函数:

import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; _≢_)
open Eq.≡-Reasoning

data Positive : Set where 
    xH : Positive
    xI : Positive -> Positive
    xO : Positive -> Positive

proof : ∀ (p q : Positive) → (p ≡ q) → ((xI p) ≡ (xI q))
proof xH xH = λ _ → refl
proof (xI p) xH = λ ()
proof (xO p) xH = λ ()  
proof xH (xI q) = λ ()
proof (xI p) (xI q) = proof p q -- 此处出现错误   
proof (xO p) (xI q) = λ ()
proof xH (xO q) = λ () 
proof (xI p) (xO q) = λ ()
proof (xO p) (xO q) = ?

递归步骤出现类型不匹配错误。

错误原因与解决方法

1. 核心问题:构造子的单射性需要显式证明

Agda不会默认认为数据类型的构造子是单射的(即xI p ≡ xI q能推导出p ≡ q),必须显式证明这一点,才能在递归调用中转换不等性证明的类型。

步骤1:证明xI和xO的单射性

import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; cong; _≢_)
open Eq.≡-Reasoning
open import Data.Empty using (⊥; ⊥-elim)

data Positive : Set where 
    xH : Positive
    xI : Positive -> Positive
    xO : Positive -> Positive

xI-inj : ∀ {p q : Positive} → xI p ≡ xI q → p ≡ q
xI-inj refl = refl

xO-inj : ∀ {p q : Positive} → xO p ≡ xO q → p ≡ q
xO-inj refl = refl

步骤2:修正gso函数的递归调用

在递归分支中,用cong函数将p ≡ q映射为xI p ≡ xI q,从而把原有的neq(类型xI p ≡ xI q → ⊥)转换为递归所需的p ≡ q → ⊥:

-- 假设Tree和get/set的定义如下(根据上下文补全)
data Tree (A : Set) : Set where
  Leaf : A -> Tree A
  Nodes : Tree A -> Tree A -- 示例构造子,根据实际定义调整

get : Positive -> Tree A -> A
get xH (Leaf v) = v
get (xI p) (Nodes t) = get p t
-- 其他get分支省略

set : Positive -> A -> Tree A -> Tree A
set xH v (Leaf _) = Leaf v
set (xI p) v (Nodes t) = Nodes (set p v t)
-- 其他set分支省略

gso : {A : Set} -> ∀ (i j : Positive) (t : Tree A) (v : A) → i ≢ j → get i (set j v t) ≡ get i t
-- 处理i和j构造子相同的情况:直接用⊥-elim消去矛盾
gso (xI p) (xI p) t v neq = ⊥-elim (neq refl)
gso (xO p) (xO p) t v neq = ⊥-elim (neq refl)
-- 递归处理xI分支
gso (xI p) (xI q) (Nodes t) v neq = 
  gso p q t v (λ eq → neq (cong xI eq))
-- 处理i和j构造子不同的情况(示例)
gso (xI p) xH t v neq = refl -- 根据实际get/set逻辑调整
gso xH (xI q) t v neq = refl
-- 其他分支同理补充

2. 辅助函数的修正

你写的proof函数其实就是库函数cong xI,不需要手动实现。如果一定要自己写,正确的写法是利用模式匹配处理相等性:

proof : ∀ (p q : Positive) → p ≡ q → xI p ≡ xI q
proof p .p refl = refl

之前的递归错误是因为proof p q的类型是p ≡ q → xI p ≡ xI q,但当前分支需要的是xI p ≡ xI q → xI (xI p) ≡ xI (xI q),类型不匹配,直接用模式匹配处理refl即可。

关键总结

  • Agda要求显式证明数据构造子的单射性,不能依赖默认推导
  • 递归调用时,需要通过cong或单射性引理转换不等性证明的类型,确保参数类型匹配
  • 对于矛盾分支(如i ≡ j但参数要求i ≢ j),用⊥-elim直接消去即可

内容的提问来源于stack exchange,提问作者Max Podpera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 07:15:31