Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ Deprecated names
homo ↦ ∙-homo
```

* In `Data.DifferenceList.Base`:
```agda
lift ↦ _++_
```

* In `Data.Fin.Properties`:
```agda
_≟_ ↦ _≡?_
Expand Down Expand Up @@ -155,6 +160,10 @@ New modules
* `Data.Bool.ListAction.Properties` for properties of conjunction and
disjunction of lists.

* `Data.DifferenceList` has been refactored to reexport the contents of two new modules:
- `Data.DifferenceList.Base`
- `Data.DifferenceList.Properties`

* A new type of lists that grow on the right.
This is typically useful to model contexts of typing rules
or type accumulators that need to be reversed in the base case.
Expand Down
81 changes: 6 additions & 75 deletions src/Data/DifferenceList.agda
Original file line number Diff line number Diff line change
@@ -1,84 +1,15 @@
------------------------------------------------------------------------
-- The Agda standard library
--
-- Lists with fast append
-- A DiffList is a List with fast append.
-- Based on Hughes' 'A NOVEL REPRESENTATION OF LISTS AND ITS APPLICATION
-- TO THE FUNCTION "REVERSE"'
-- DiffList is the Cayley representation for the List.++ monoid.
------------------------------------------------------------------------

{-# OPTIONS --without-K --safe #-}

module Data.DifferenceList where

open import Level using (Level)
open import Data.List.Base as List using (List)
open import Function.Base using (_⟨_⟩_)
open import Data.Nat.Base using (ℕ)

private
variable
a b : Level
A : Set a
B : Set b

------------------------------------------------------------------------
-- Type definition and list function lifting

DiffList : Set a → Set a
DiffList A = List A → List A

lift : (List A → List A) → (DiffList A → DiffList A)
lift f xs = λ k → f (xs k)

------------------------------------------------------------------------
-- Building difference lists

infixr 5 _∷_ _++_

[] : DiffList A
[] = λ k → k

_∷_ : A → DiffList A → DiffList A
_∷_ x = lift (x List.∷_)

[_] : A → DiffList A
[ x ] = x ∷ []

_++_ : DiffList A → DiffList A → DiffList A
xs ++ ys = λ k → xs (ys k)

infixl 6 _∷ʳ_
_∷ʳ_ : DiffList A → A → DiffList A
xs ∷ʳ x = λ k → xs (x List.∷ k)

------------------------------------------------------------------------
-- Conversion back and forth with List

toList : DiffList A → List A
toList xs = xs List.[]

-- fromList xs is linear in the length of xs.

fromList : List A → DiffList A
fromList xs = λ k → xs ⟨ List._++_ ⟩ k

------------------------------------------------------------------------
-- Transforming difference lists

-- It is OK to use List._++_ here, since map is linear in the length of
-- the list anyway.

map : (A → B) → DiffList A → DiffList B
map f xs = λ k → List.map f (toList xs) ⟨ List._++_ ⟩ k

-- concat is linear in the length of the outer list.

concat : DiffList (DiffList A) → DiffList A
concat xs = concat′ (toList xs)
where
concat′ : List (DiffList A) → DiffList A
concat′ = List.foldr _++_ []

take : ℕ → DiffList A → DiffList A
take n = lift (List.take n)

drop : ℕ → DiffList A → DiffList A
drop n = lift (List.drop n)
open import Data.DifferenceList.Base public
open import Data.DifferenceList.Properties public
Comment thread
mikedelorimier marked this conversation as resolved.
94 changes: 94 additions & 0 deletions src/Data/DifferenceList/Base.agda
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
------------------------------------------------------------------------
-- The Agda standard library
--
-- DiffList: basic types and operations
------------------------------------------------------------------------

{-# OPTIONS --without-K --safe #-}

module Data.DifferenceList.Base where

open import Data.List.Base as List using (List)
open import Data.Nat.Base using (ℕ)
open import Function using (_∘′_; id)
open import Level using (Level)

private
variable
a b : Level
A : Set a
B : Set b


------------------------------------------------------------------------
-- Type definition

DiffList : Set a → Set a
DiffList A = List A → List A

------------------------------------------------------------------------
-- Building difference lists

infixr 5 _∷_ _++_

[] : DiffList A
[] = id

[_] : A → DiffList A
[ x ] = x List.∷_

_++_ : DiffList A → DiffList A → DiffList A
_++_ = _∘′_

_∷_ : A → DiffList A → DiffList A
x ∷ xs = [ x ] ++ xs

infixl 6 _∷ʳ_
_∷ʳ_ : DiffList A → A → DiffList A
xs ∷ʳ x = xs ++ [ x ]

------------------------------------------------------------------------
-- Conversion back and forth with List

toList : DiffList A → List A
toList xs = xs List.[]

-- fromList xs is linear in the length of xs.

fromList : List A → DiffList A
fromList = List._++_

------------------------------------------------------------------------
-- Transforming difference lists

-- It is OK to use List._++_ here, since map is linear in the length of
-- the list anyway.

map : (A → B) → DiffList A → DiffList B
map f = fromList ∘′ List.map f ∘′ toList

-- concat is linear in the length of the outer list.

concat : DiffList (DiffList A) → DiffList A
concat = List.foldr _++_ [] ∘′ toList

take : ℕ → DiffList A → DiffList A
take n = List.take n ++_

drop : ℕ → DiffList A → DiffList A
drop n = List.drop n ++_


------------------------------------------------------------------------
-- DEPRECATED NAMES
------------------------------------------------------------------------
-- Please use the new names as continuing support for the old names is
-- not guaranteed.

-- Version 3.0
lift : DiffList A → DiffList A → DiffList A
lift = _++_
{-# WARNING_ON_USAGE lift
"Warning: lift was deprecated in v3.0.
Please use _++_ instead."
#-}
84 changes: 84 additions & 0 deletions src/Data/DifferenceList/Properties.agda
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
------------------------------------------------------------------------
-- The Agda standard library
--
-- Properties of operations on DiffList
------------------------------------------------------------------------

{-# OPTIONS --without-K --safe #-}

module Data.DifferenceList.Properties where

open import Data.DifferenceList.Base
using (DiffList; fromList; toList; []; _∷_; [_]; _++_; _∷ʳ_; map)
open import Data.List as List using (List)
open import Data.List.Properties using (++-assoc; ++-identityʳ)
open import Function using (id)
open import Level using (Level)
open import Relation.Binary.PropositionalEquality
using (_≡_; refl; cong; _≗_; module ≡-Reasoning)

open ≡-Reasoning

private
variable
a b : Level
A : Set a
B : Set b
xs xs₁ xs₂ : List A
ys ys₁ ys₂ : DiffList A


------------------------------------------------------------------------
-- Relation between Lists and equivalent DiffLists

infix 4 _∼_
_∼_ : List A → DiffList A → Set _
xs ∼ ys = fromList xs ≗ ys

------------------------------------------------------------------------
-- Properties of fromList and toList

∼-fromList : xs ∼ fromList xs
∼-fromList _ = refl

toList∘fromList : (xs : List A) → toList (fromList xs) ≡ xs
toList∘fromList = ++-identityʳ

toList⁺ : xs ∼ ys → xs ≡ toList ys
toList⁺ {xs = xs} {ys} xs∼ys = begin
xs ≡⟨ ++-identityʳ xs ⟨
xs List.++ List.[] ≡⟨ xs∼ys List.[] ⟩
ys List.[] ≡⟨⟩
toList ys ∎

------------------------------------------------------------------------
-- Properties of operations that preserve _∼_

[]⁺ : List.[] {A = A} ∼ []
[]⁺ _ = refl

[_]⁺ : (x : A) → List.[ x ] ∼ [ x ]
[_]⁺ _ _ = refl

++⁺ : xs₁ ∼ ys₁ → xs₂ ∼ ys₂ → xs₁ List.++ xs₂ ∼ ys₁ ++ ys₂
++⁺ {xs₁ = xs₁} {ys₁ = ys₁} {xs₂ = xs₂} {ys₂ = ys₂}
xs₁∼ys₁ xs₂∼ys₂ k = begin
(xs₁ List.++ xs₂) List.++ k ≡⟨ ++-assoc xs₁ xs₂ k ⟩
xs₁ List.++ (xs₂ List.++ k) ≡⟨ cong (xs₁ List.++_) (xs₂∼ys₂ k) ⟩
xs₁ List.++ ys₂ k ≡⟨ xs₁∼ys₁ (ys₂ k) ⟩
ys₁ (ys₂ k) ≡⟨⟩
(ys₁ ++ ys₂) k ∎

∷⁺ : (x : A) → xs ∼ ys → x List.∷ xs ∼ x ∷ ys
∷⁺ {xs = xs} {ys} x xs~ys k = cong (x List.∷_) (xs~ys k)

++-∷⁺ : (x : A) → xs₁ ∼ ys₁ → xs₂ ∼ ys₂ →
xs₁ List.++ x List.∷ xs₂ ∼ ys₁ ++ x ∷ ys₂
++-∷⁺ x xs₁∼ys₁ xs₂∼ys₂ = ++⁺ xs₁∼ys₁ (∷⁺ x xs₂∼ys₂)

∷ʳ⁺ : (x : A) → xs ∼ ys → xs List.∷ʳ x ∼ ys ∷ʳ x
∷ʳ⁺ {xs = xs} {ys} x xs∼ys k = ++⁺ xs∼ys [ x ]⁺ k

map⁺ : (f : A → B) → xs ∼ ys → List.map f xs ∼ map f ys
map⁺ f xs∼ys k =
cong (λ xs → fromList (List.map f xs) k) (toList⁺ xs∼ys)
Comment thread
jamesmckinna marked this conversation as resolved.
Loading