------------------------------------------------------------------------
-- The Agda standard library
--
-- Binary Trees
------------------------------------------------------------------------

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

module Data.Tree.Binary where

open import Level using (Level; _⊔_)
open import Data.List.Base using (List)
open import Data.DifferenceList as DiffList using (DiffList; []; _∷_; _∷ʳ_; _++_)
open import Data.Nat.Base using (; zero; suc; _+_)
open import Function.Base
open import Relation.Binary.PropositionalEquality

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

data Tree (A : Set a) : Set a where
  leaf : Tree A
  node : Tree A  A  Tree A  Tree A

map : (A  B)  Tree A  Tree B
map f leaf         = leaf
map f (node l m r) = node (map f l) (f m) (map f r)

size : Tree A  
size leaf         = 0
size (node l m r) = size l + suc (size r)

foldr : (B  A  B  B)  B  Tree A  B
foldr nd lf leaf         = lf
foldr nd lf (node l m r) = nd (foldr nd lf l) m (foldr nd lf r)

------------------------------------------------------------------------
-- Extraction to lists, depth first and left to right.

module Prefix where

  toDiffList : Tree A  DiffList A
  toDiffList = foldr  l m r  m  l ++ r) []

  toList : Tree A  List A
  toList = DiffList.toList ∘′ toDiffList

module Infix where

  toDiffList : Tree A  DiffList A
  toDiffList = foldr  l m r  l ++ m  r) []

  toList : Tree A  List A
  toList = DiffList.toList ∘′ toDiffList

module Suffix where

  toDiffList : Tree A  DiffList A
  toDiffList = foldr  l m r  l ++ r ∷ʳ m) []

  toList : Tree A  List A
  toList = DiffList.toList ∘′ toDiffList