Agda的标准库Data.AVL.Sets包含Data.String作为值

时间:2016-03-28 19:10:30

标签: agda

我试图弄清楚如何在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的东西是什么。似乎字符串总顺序的逐点定义存在一些问题,但我无法弄清楚。

1 个答案:

答案 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 ,以便您可以轻松访问代码,查看导入等。