我试图弄清楚如何在Data.AVL.Sets
模块中使用基于AVL树的Agda标准库实现有限集。我能够成功地使用ℕ
作为值,并使用以下代码。
import Data.AVL.Sets
open import Data.Nat.Properties as ℕ
open import Relation.Binary using (module StrictTotalOrder)
open Data.AVL.Sets (StrictTotalOrder.isStrictTotalOrder ℕ.strictTotalOrder)
test = singleton 5
现在我希望实现相同的目标,但使用Data.String
作为值。似乎不是相应的Data.String.Properties
模块,但Data.String
导出strictTotalOrder : StrictTotalOrder _ _ _
我认为合适。
然而,只是根据这个假设严格更换模块失败了。
import Data.AVL.Sets
open import Data.String as String
open import Relation.Binary using (module StrictTotalOrder)
open Data.AVL.Sets (StrictTotalOrder.isStrictTotalOrder String.strictTotalOrder)
产生错误
.Relation.Binary.List.Pointwise.Rel
(StrictTotalOrder._≈_ .Data.Char.strictTotalOrder) (toList x) (toList x₁)
!= x .Relation.Binary.Core.Dummy.≡ x₁ of type Set
when checking that the expression
StrictTotalOrder.isStrictTotalOrder String.strictTotalOrder
has type
Relation.Binary.IsStrictTotalOrder .Relation.Binary.Core.Dummy._≡_
__<__3
我觉得很难详细解压,因为我不知道Core.Dummy
的东西是什么。似乎字符串总顺序的逐点定义存在一些问题,但我无法弄清楚。
答案 0 :(得分:6)
如果查看Data.AVL.Sets
,您可以看到它是通过与等价关系_≡_
(在Relation.Binary.PropositionalEquality
中定义)相关联的严格总订单进行参数化的:
module Data.AVL.Sets
{k ℓ} {Key : Set k} {_<_ : Rel Key ℓ}
(isStrictTotalOrder : IsStrictTotalOrder _≡_ _<_)
where
现在我们可以看看如何定义String
上的严格总排序。我们首先将String
转换为List Char
,然后根据列表的严格词典排序对它们进行比较:
strictTotalOrder =
On.strictTotalOrder
(StrictLex.<-strictTotalOrder Char.strictTotalOrder)
toList
如果我们深入研究StrictLex.<-strictTotalOrder
的代码,我们可以看到与List
Char
Pointwise.isEquivalence
相关联的等价关系是使用逐点提升Char
建立的。无论Pointwise.isEquivalence
s的等价关系是什么。
但data Rel {a b ℓ} {A : Set a} {B : Set b}
(_∼_ : REL A B ℓ) : List A → List B → Set (a ⊔ b ⊔ ℓ) where
[] : Rel _∼_ [] []
_∷_ : ∀ {x xs y ys} (x∼y : x ∼ y) (xs∼ys : Rel _∼_ xs ys) →
Rel _∼_ (x ∷ xs) (y ∷ ys)
是根据此数据类型定义的:
_≡_
因此,当Agda期望与Rel _ on toList
相关联的严格总订单时,我们会向其提供与_≡_
相关联的严格总订单,而该订单无法统一。
我们如何从这里继续前进?那么,您可以在字符串上定义自己的严格总订单。或者,您可以尝试将当前的一个转换为一个IsStrictTotalOrder R O
是使用的等效项。这是我将在本文的其余部分中做的事情。
所以,我想重用具有不同等价关系R′
的{{1}}。诀窍是要注意,如果可以将值从R a b
传输到R′ a b
那么,我应该没问题!因此,我引入了一个RawIso A B
概念,其中指出我们始终可以将值从A
传输到B
,反之亦然:
record RawIso {ℓ : Level} (A B : Set ℓ) : Set ℓ where
field
push : A → B
pull : B → A
open RawIso public
然后我们可以证明RawIso
保留了很多属性:
RawIso-IsEquivalence :
{ℓ ℓ′ : Level} {A : Set ℓ} {R R′ : Rel A ℓ′} →
(iso : {a b : A} → RawIso (R a b) (R′ a b)) →
IsEquivalence R → IsEquivalence R′
RawIso-IsEquivalence = ...
RawIso-Trichotomous :
{ℓ ℓ′ ℓ′′ : Level} {A : Set ℓ} {R R′ : Rel A ℓ′} {O : Rel A ℓ′′} →
(iso : {a b : A} → RawIso (R a b) (R′ a b)) →
Trichotomous R O → Trichotomous R′ O
RawIso-Trichotomous = ...
RawIso-Respects₂ :
{ℓ ℓ′ ℓ′′ : Level} {A : Set ℓ} {R R′ : Rel A ℓ′} {O : Rel A ℓ′′} →
(iso : {a b : A} → RawIso (R a b) (R′ a b)) →
O Respects₂ R → O Respects₂ R′
RawIso-Respects₂ = ...
所有这些引理可以合并,以证明给定严格的总订单,我们可以通过RawIso
建立一个新的:
RawIso-IsStrictTotalOrder :
{ℓ ℓ′ ℓ′′ : Level} {A : Set ℓ} {R R′ : Rel A ℓ′} {O : Rel A ℓ′′} →
(iso : {a b : A} → RawIso (R a b) (R′ a b)) →
IsStrictTotalOrder R O → IsStrictTotalOrder R′ O
RawIso-IsStrictTotalOrder = ...
现在我们知道我们可以沿着这些RawIso
传输严格的总订单,我们只需要证明Data.String
中定义的严格总订单使用的等价关系在{{1}与命题平等。它(几乎)只是展开定义的问题。唯一的问题是字符的相等性是通过首先将它们转换为自然数然后使用命题相等来定义的。但是使用的toNat
function没有明确的属性(例如,与toList
and fromList
相比,它们被称为反转)!我投入了这个黑客,我认为它应该没问题,但如果有人有更好的解决方案,我很想知道它!
RawIso
无论如何,既然你有这个,你可以展开定义并证明:
toNat-injective : {c d : Char} → toNat c ≡ toNat d → c ≡ d
toNat-injective {c} pr with toNat c
toNat-injective refl | ._ = trustMe -- probably unsafe
where open import Relation.Binary.PropositionalEquality.TrustMe
允许你
rawIso : {a b : String} →
RawIso ((Ptwise.Rel (_≡_ on toNat) on toList) a b) (a ≡ b)
rawIso {a} {b} = record { push = `push ; pull = `pull } where
`push : {a b : String} → (Ptwise.Rel (_≡_ on toNat) on toList) a b → a ≡ b
`push {a} {b} pr =
begin
a ≡⟨ sym (fromList∘toList a) ⟩
fromList (toList a) ≡⟨ cong fromList (aux pr) ⟩
fromList (toList b) ≡⟨ fromList∘toList b ⟩
b
∎ where
aux : {xs ys : List Char} → Ptwise.Rel (_≡_ on toNat) xs ys → xs ≡ ys
aux = Ptwise.rec (λ {xs} {ys} _ → xs ≡ ys)
(cong₂ _∷_ ∘ toNat-injective) refl
`pull : {a b : String} → a ≡ b → (Ptwise.Rel (_≡_ on toNat) on toList) a b
`pull refl = Ptwise.refl refl
呼!
我上传了raw gist ,以便您可以轻松访问代码,查看导入等。