我在弄清楚如何在Agda中使用String键正确制作Map时遇到了一些麻烦。我有以下内容:
import Data.AVL.IndexedMap
Var = String
data Type where -- ...
alwaysType : Var -> Set
alwaysType _ = Type
open Data.AVL.IndexedMap alwaysType (StrictTotalOrder.isStrictTotalOrder Data.String.strictTotalOrder)
这给出了错误:
String != Σ String _Key_90 of type Set
when checking that the expression
StrictTotalOrder.isStrictTotalOrder strictTotalOrder has type
Relation.Binary.IsStrictTotalOrder .Agda.Builtin.Equality._≡_
__<__91
打开Map模块的正确方法是什么?
Data.AVL.IndexedMap
模块用于(有限)映射,其中存在键和值的类型族,并且与给定键相关联的值与该值共享索引。
这不是你想要的,因为你想要所有的钥匙都是String
s。所以只需使用Data.AVL
(即带有非索引键的版本):
open import Data.String using (String)
open import Function using (const)
Key = String
postulate
Value : Set
open import Relation.Binary using (StrictTotalOrder)
open import Data.AVL (const Value) (StrictTotalOrder.isStrictTotalOrder Data.String.strictTotalOrder)
不幸的是,这仍然没有成功:
.Relation.Binary.List.Pointwise.Rel
(StrictTotalOrder._≈_ .Data.Char.strictTotalOrder)
(Data.String.toList x) (Data.String.toList x₁)
!= x .Agda.Builtin.Equality.≡ x₁ of type Set
when checking that the expression
StrictTotalOrder.isStrictTotalOrder Data.String.strictTotalOrder
has type IsStrictTotalOrder .Agda.Builtin.Equality._≡_ __<__10
这是因为Data.String.strictTotalOrder
使用逐点相等(在构成ℕ
的Char
的String
值列表中),而Data.AVL
需要命题相等。所以完全相同的例子可以使用,例如,ℕ
键:
open import Data.Nat using (ℕ)
open import Function using (const)
Key = ℕ
postulate
Value : Set
import Data.Nat.Properties
open import Relation.Binary using (StrictTotalOrder)
open import Data.AVL (const Value) (StrictTotalOrder.isStrictTotalOrder Data.Nat.Properties.strictTotalOrder)
因此,下一步需要将StrictTotalOrder.isStrictTotalOrder Data.String.strictTotalOrder
转换为IsStrictTotalOrder (_≡_ {A = String}) _
类型。我现在就把它留给别人,但是我很乐意稍后再看,当我有时间的时候,如果你不能让它工作,也没有其他人接受它。
编辑添加:这是一种(可能非常复杂的)将StrictTotalOrder
从标准库转换为使用命题平等的String
的方法:
open import Function using (const; _∘_; _on_)
open import Relation.Binary
open import Data.String
using (String; toList∘fromList; fromList∘toList)
renaming (toList to stringToList; fromList to stringFromList)
open import Relation.Binary.List.Pointwise as Pointwise
open import Relation.Binary.PropositionalEquality as P hiding (trans)
open import Data.Char.Base renaming (toNat to charToNat)
STO : StrictTotalOrder _ _ _
STO = record
{ Carrier = String
; _≈_ = _≡_
; _<_ = _<_
; isStrictTotalOrder = record
{ isEquivalence = P.isEquivalence
; trans = λ {x} {y} {z} → trans {x} {y} {z}
; compare = compare
}
}
where
open StrictTotalOrder Data.String.strictTotalOrder
renaming (isEquivalence to string-isEquivalence; compare to string-compare)
-- It feels like this should be defined somewhere in the
-- standard library, but I can't find it...
primCharToNat-inj : ∀ {x y} → primCharToNat x ≡ primCharToNat y → x ≡ y
primCharToNat-inj _ = trustMe
where
open import Relation.Binary.PropositionalEquality.TrustMe
open import Data.List
lem : ∀ {xs ys} → Pointwise.Rel (_≡_ on primCharToNat) xs ys → xs ≡ ys
lem [] = P.refl
lem {x ∷ xs} {y ∷ ys} (x∼y ∷ p) with primCharToNat-inj {x} {y} x∼y
lem {x ∷ xs} {_ ∷ ys} (x∼y ∷ p) | P.refl = cong _ (lem p)
≡-from-≈ : {s s′ : String} → s ≈ s′ → s ≡ s′
≡-from-≈ {s} {s′} p = begin
s ≡⟨ sym (fromList∘toList _) ⟩
stringFromList (stringToList s) ≡⟨ cong stringFromList (lem p) ⟩
stringFromList (stringToList s′) ≡⟨ fromList∘toList _ ⟩
s′ ∎
where
open P.≡-Reasoning
≈-from-≡ : {s s′ : String} → s ≡ s′ → s ≈ s′
≈-from-≡ {s} {_} refl = string-refl {s}
where
open IsEquivalence string-isEquivalence renaming (refl to string-refl) using ()
compare : (x y : String) → Tri (x < y) (x ≡ y) _
compare x y with string-compare x y
compare x y | tri< a ¬b ¬c = tri< a (¬b ∘ ≈-from-≡) ¬c
compare x y | tri≈ ¬a b ¬c = tri≈ ¬a (≡-from-≈ b) ¬c
compare x y | tri> ¬a ¬b c = tri> ¬a (¬b ∘ ≈-from-≡) c
请注意,标准库的Data.AVL
已更新为接受严格的总订单,而不是基于命题相等。
这些天它很简单:
open import Data.String.Properties
open import Data.AVL strictTotalOrder