如何从Data.AVL.Tree获取值列表?

时间:2015-09-05 22:58:22

标签: agda dependent-type

我可以轻松获取密钥列表,如下所示:

open import Relation.Binary
open import Relation.Binary.PropositionalEquality using (_≡_)

module AVL-Tree-Functions
  { k v ℓ } { Key : Set k }
  ( Value : Key → Set v )
  { _<_ : Rel Key ℓ }
  ( isStrictTotalOrder : IsStrictTotalOrder _≡_ _<_ )
  where

  open import Data.AVL Value isStrictTotalOrder public

  open import Data.List.Base
  open import Function
  open import Data.Product

  keys : Tree → List Key
  keys = Data.List.Base.map proj₁ ∘ toList

但我不清楚如何指定返回值列表的函数类型。这是我的第一次尝试:

  -- this fails to typecheck
  values : Tree → List Value
  values = Data.List.Base.map proj₂ ∘ toList

相关地,我也对Data.AVL中Value的声明感到困惑。使用( Value : Key → Set v ),树中每个Value的类型看起来都取决于密钥?或类似的东西。然后我认为proj 2会返回Set v类型的东西,所以我尝试了这个:

  -- this also fails to typecheck
  values : Tree → List (Set v)
  values = Data.List.Base.map proj₂ ∘ toList

但这也不起作用(它失败并出现不同的错误)。请说明如何从Data.AVL.Tree获取值列表(或解释为什么它不可能)。奖金:解释为什么我的两次尝试都失败了。

P.S。这是使用Agda的版本2.4.2.3和agda-stdlib。

2 个答案:

答案 0 :(得分:5)

  

看起来树中每个Value的类型都依赖于   键?

是。这就是为什么你的代码没有进行类型检查的原因 - List s是同质的,但不同的Value具有不同的索引(即依赖于不同的Key s)因此不同类型。

您可以使用异类列表,如 gallais &#39;回答,但索引列表可能就足够了:

open import Level

data IList {ι α} {I : Set ι} (A : I -> Set α) : Set (ι ⊔ α) where
  []ᵢ  : IList A
  _∷ᵢ_ : ∀ {i} -> A i -> IList A -> IList A

projs₂ : ∀ {α β} {A : Set α} {B : A -> Set β} -> List (Σ A B) -> IList B
projs₂  []            = []ᵢ
projs₂ ((x , y) ∷ ps) = y ∷ᵢ projs₂ ps

或者你可以结合使用这些技术:

data IHList {ι α} {I : Set ι} (A : I -> Set α) : List I -> Set (ι ⊔ α) where
  []ᵢ  : IHList A []
  _∷ᵢ_ : ∀ {i is} -> A i -> IHList A is -> IHList A (i ∷ is)

projs₂ : ∀ {α β} {A : Set α} {B : A -> Set β}
       -> (xs : List (Σ A B)) -> IHList B (Data.List.Base.map proj₁ xs)
projs₂  []            = []ᵢ
projs₂ ((x , y) ∷ ps) = y ∷ᵢ projs₂ ps

答案 1 :(得分:3)

Value : Key → Set v的含义是值的类型可能取决于与之关联的键。这意味着AVL树可能包含布尔值,Nats等,只要它们存储的密钥反映了这一事实。有点像记录可以存储不同类型的值这一事实(类型由字段名称决定)。

现在,它们有不同的方法:你可以将整个树的内容提取到键/值对的列表中(因为列表的元素都是相同的,你需要在这里建立一对,以便一切具有相同的类型Σ Key Value)。这就是toList的作用。

另一种方法是使用通常称为HList(H代表异构)的东西,它存储在类型级别的列表中每个元素的类型具有。我在这里通过对元素集的归纳来定义它是出于大小原因,但它根本不是至关重要的(如果你将它定义为数据类型,它会活得更高一层):

open import Level
open import Data.Unit

HList : {ℓ : Level} (XS : List (Set ℓ)) → Set ℓ
HList []       = Lift ⊤
HList (X ∷ XS) = X × HList XS

现在,您可以提供HList值的类型。给定t一个Tree,它会使用您的keys提取密钥列表,并通过在列表上映射Set将其转换为Value

values : (t : Tree) → HList (List.map Value (keys t))

然后可以借助于toList生成的列表中的辅助函数来提取值:

values t = go (toList t) where

  go : (kvs : List (Σ Key Value)) → HList (List.map Value $ List.map proj₁ kvs)
  go []         = lift tt
  go (kv ∷ kvs) = proj₂ kv , go kvs