Skip to content

Commit 423a351

Browse files
gallaisMatthewDaggitt
authored andcommitted
[ new ] add rose trees (#1035)
1 parent 77ec62a commit 423a351

File tree

7 files changed

+220
-10
lines changed

7 files changed

+220
-10
lines changed

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ warnings are attached to all deprecated names to discourage their use.
133133
Other major additions
134134
---------------------
135135

136-
* New modules
136+
* Added new modules:
137137
```agda
138138
Codata.Cowriter.Bisimilarity
139139
@@ -145,16 +145,19 @@ Other major additions
145145
Data.Tree.Binary.Properties
146146
Data.Tree.Binary.Relation.Unary.All
147147
Data.Tree.Binary.Relation.Unary.All.Properties
148+
Data.Tree.Rose
149+
Data.Tree.Rose.Properties
148150
149151
Text.Pretty.Core
150152
Text.Pretty
151-
152153
Text.Tabular.Base
153154
Text.Tabular.List
154155
Text.Tabular.Vec
156+
Text.Tree.Linear
155157
156158
README.Text.Pretty
157159
README.Text.Tabular
160+
README.Text.Tree
158161
```
159162

160163
* Added induction over subsets to `Data.Fin.Subset.Induction`.

README.agda

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,13 +294,18 @@ import README.Inspect
294294

295295
import README.Text.Printf
296296

297+
-- Showcasing the pretty printing module
298+
299+
import README.Text.Pretty
300+
297301
-- Explaining how to display tables of strings:
298302

299303
import README.Text.Tabular
300304

301-
-- Showcasing the pretty printing module
305+
-- Explaining how to display a tree:
306+
307+
import README.Text.Tree
302308

303-
import README.Text.Pretty
304309

305310
------------------------------------------------------------------------
306311
-- Core modules

README/Text/Tree.agda

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Examples of pretty printing of rose trees
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --without-K --safe --sized-types #-}
8+
9+
module README.Text.Tree where
10+
11+
open import Data.List.Base
12+
open import Data.String.Base
13+
open import Data.Tree.Rose
14+
open import Function.Base
15+
open import Agda.Builtin.Equality
16+
17+
------------------------------------------------------------------------
18+
-- We import the module defining the pretty printer for rose trees
19+
20+
open import Text.Tree.Linear
21+
22+
------------------------------------------------------------------------
23+
-- Example
24+
25+
_ : unlines (display
26+
$ node [ "one" ]
27+
(node [ "two" ] []
28+
∷ node ("three""and""four" ∷ [])
29+
(node [ "five" ] []
30+
∷ node [ "six" ] (node [ "seven" ] [] ∷ [])
31+
∷ node [ "eight" ] []
32+
∷ [])
33+
∷ node [ "nine" ]
34+
(node [ "ten" ] []
35+
∷ node [ "eleven" ] [] ∷ [])
36+
∷ []))
37+
"one
38+
\ \ ├ two
39+
\ \ ├ three
40+
\ \ │ and
41+
\ \ │ four
42+
\ \ │ ├ five
43+
\ \ │ ├ six
44+
\ \ │ │ └ seven
45+
\ \ │ └ eight
46+
\ \ └ nine
47+
\ \ ├ ten
48+
\ \ └ eleven"
49+
_ = refl

src/Data/List/Base.agda

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ module Data.List.Base where
1313

1414
open import Data.Bool.Base as Bool
1515
using (Bool; false; true; not; _∧_; _∨_; if_then_else_)
16-
open import Data.Fin using (Fin; zero; suc)
17-
open import Data.Maybe.Base as Maybe using (Maybe; nothing; just; maybe)
16+
open import Data.Fin.Base using (Fin; zero; suc)
17+
open import Data.Maybe.Base as Maybe using (Maybe; nothing; just; maybe)
1818
open import Data.Nat.Base as ℕ using (ℕ; zero; suc; _+_; _*_ ; _≤_ ; s≤s)
1919
open import Data.Product as Prod using (_×_; _,_)
20-
open import Data.Sum as Sum using (_⊎_; inj₁; inj₂)
20+
open import Data.Sum.Base as Sum using (_⊎_; inj₁; inj₂)
2121
open import Data.These.Base as These using (These; this; that; these)
22-
open import Function using (id; _∘_ ; _∘′_; const; flip)
22+
open import Function.Base using (id; _∘_ ; _∘′_; const; flip)
2323
open import Level using (Level)
2424
open import Relation.Nullary using (does)
2525
open import Relation.Unary using (Pred; Decidable)
@@ -335,11 +335,11 @@ xs ∷ʳ x = xs ++ [ x ]
335335

336336
infixr 5 _?∷_
337337
_?∷_ : Maybe A List A List A
338-
_?∷_ = maybe _∷_ id
338+
_?∷_ = maybe _∷_ id
339339

340340
infixl 6 _∷ʳ?_
341341
_∷ʳ?_ : List A Maybe A List A
342-
xs ∷ʳ? x = maybe (xs ∷ʳ_) xs x
342+
xs ∷ʳ? x = maybe (xs ∷ʳ_) xs x
343343

344344

345345
-- Backwards initialisation

src/Data/Tree/Rose.agda

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Rose trees
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --without-K --safe --sized-types #-}
8+
9+
module Data.Tree.Rose where
10+
11+
open import Level using (Level)
12+
open import Size
13+
open import Data.List.Base as List using (List; []; _∷_)
14+
open import Data.Nat.Base as ℕ using (ℕ; zero; suc)
15+
import Data.Nat.Properties as ℕₚ
16+
open import Data.List.Extrema.Nat
17+
open import Function.Base using (_∘_)
18+
19+
private
20+
variable
21+
a b : Level
22+
A : Set a
23+
B : Set b
24+
i : Size
25+
26+
------------------------------------------------------------------------
27+
-- Type and basic constructions
28+
29+
data Rose (A : Set a) : Size Set a where
30+
node : (a : A) (ts : List (Rose A i)) Rose A (↑ i)
31+
32+
leaf : A Rose A ∞
33+
leaf a = node a []
34+
35+
------------------------------------------------------------------------
36+
-- Transforming rose trees
37+
38+
map : (A B) Rose A i Rose B i
39+
map f (node a ts) = node (f a) (List.map (map f) ts)
40+
41+
------------------------------------------------------------------------
42+
-- Reducing rose trees
43+
44+
foldr : (A List B B) Rose A i B
45+
foldr n (node a ts) = n a (List.map (foldr n) ts)
46+
47+
depth : Rose A i
48+
depth (node a ts) = suc (max 0 (List.map depth ts))

src/Data/Tree/Rose/Properties.agda

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Properties of rose trees
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --without-K --safe --sized-types #-}
8+
9+
module Data.Tree.Rose.Properties where
10+
11+
open import Level using (Level)
12+
open import Size
13+
open import Data.List.Base as List using (List)
14+
open import Data.List.Extrema.Nat
15+
import Data.List.Properties as Listₚ
16+
open import Data.Nat.Base using (ℕ; zero; suc)
17+
open import Data.Tree.Rose
18+
open import Function.Base
19+
open import Relation.Binary.PropositionalEquality
20+
open ≡-Reasoning
21+
22+
private
23+
variable
24+
a b c : Level
25+
A : Set a
26+
B : Set b
27+
C : Set c
28+
i : Size
29+
30+
------------------------------------------------------------------------
31+
-- map properties
32+
33+
map-compose : (f : A B) (g : B C)
34+
map {i = i} (g ∘′ f) ≗ map {i = i} g ∘′ map {i = i} f
35+
map-compose f g (node a ts) = cong (node (g (f a))) $ begin
36+
List.map (map (g ∘′ f)) ts ≡⟨ Listₚ.map-cong (map-compose f g) ts ⟩
37+
List.map (map g ∘ map f) ts ≡⟨ Listₚ.map-compose ts ⟩
38+
List.map (map g) (List.map (map f) ts) ∎
39+
40+
depth-map : (f : A B) (t : Rose A i) depth {i = i} (map {i = i} f t) ≡ depth {i = i} t
41+
depth-map f (node a ts) = cong (suc ∘′ max 0) $ begin
42+
List.map depth (List.map (map f) ts) ≡˘⟨ Listₚ.map-compose ts ⟩
43+
List.map (depth ∘′ map f) ts ≡⟨ Listₚ.map-cong (depth-map f) ts ⟩
44+
List.map depth ts ∎
45+
46+
------------------------------------------------------------------------
47+
-- foldr properties
48+
49+
foldr-map : (f : A B) (n : B List C C) (ts : Rose A i)
50+
foldr {i = i} n (map {i = i} f ts) ≡ foldr {i = i} (n ∘′ f) ts
51+
foldr-map f n (node a ts) = cong (n (f a)) $ begin
52+
List.map (foldr n) (List.map (map f) ts) ≡˘⟨ Listₚ.map-compose ts ⟩
53+
List.map (foldr n ∘′ map f) ts ≡⟨ Listₚ.map-cong (foldr-map f n) ts ⟩
54+
List.map (foldr (n ∘′ f)) ts ∎

src/Text/Tree/Linear.agda

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- 1 dimensional pretty printing of rose trees
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --without-K --safe --sized-types #-}
8+
9+
module Text.Tree.Linear where
10+
11+
open import Level using (Level)
12+
open import Size
13+
open import Data.Bool.Base using (Bool; true; false; if_then_else_; _∧_)
14+
open import Data.DifferenceList as DList renaming (DiffList to DList) using ()
15+
open import Data.List.Base as List using (List; []; [_]; _∷_; _∷ʳ_)
16+
open import Data.Nat.Base using (ℕ; _∸_)
17+
open import Data.Product using (_×_; _,_)
18+
open import Data.String.Base
19+
open import Data.Tree.Rose using (Rose; node)
20+
open import Function.Base using (flip)
21+
22+
private
23+
variable
24+
a : Level
25+
A : Set a
26+
i : Size
27+
28+
display : Rose (List String) i List String
29+
display t = DList.toList (go (([] , t) ∷ [])) where
30+
31+
padding : Bool List Bool String String
32+
padding dir? [] str = str
33+
padding dir? (b ∷ bs) str =
34+
(if dir? ∧ List.null bs
35+
then if b then " ├ " else " └ "
36+
else if b then " │ " else " ")
37+
++ padding dir? bs str
38+
39+
nodePrefixes : List A List Bool
40+
nodePrefixes as = true ∷ List.replicate (List.length as ∸ 1) false
41+
42+
childrenPrefixes : List A List Bool
43+
childrenPrefixes as = List.replicate (List.length as ∸ 1) true ∷ʳ false
44+
45+
go : List (List Bool × Rose (List String) i) DList String
46+
go [] = DList.[]
47+
go ((bs , node a ts₁) ∷ ts) =
48+
let bs′ = List.reverse bs in
49+
DList.fromList (List.zipWith (flip padding bs′) (nodePrefixes a) a)
50+
DList.++ go (List.zip (List.map (_∷ bs) (childrenPrefixes ts₁)) ts₁)
51+
DList.++ go ts

0 commit comments

Comments
 (0)