{-# OPTIONS --cubical --safe #-}
module TreeFold.Indexed where
open import Prelude
open import Data.Binary using (πΉ; 0α΅; 1α΅_; 2α΅_; β¦_ββ§; β¦_ββ§)
open import Data.Binary.Increment using (inc)
open import Data.Binary.Properties.Isomorphism
open import Data.Nat
private
variable
n m : β
t : Level
N : β β Type t
ns : πΉ
double : β β β
double n = n * 2
2^_*_ : β β β β β
2^ zero * m = m
2^ suc n * m = double (2^ n * m)
infixr 5 _1β·_ _2β·_
data Array (T : β β Type a) : πΉ β Type a where
[] : Array T 0α΅
_1β·_ : T 1 β Array (T β double) ns β Array T (1α΅ ns)
_2β·_ : T 2 β Array (T β double) ns β Array T (2α΅ ns)
cons : (β n β N n β N n β N (double n)) β N 1 β Array N ns β Array N (inc ns)
cons branch x [] = x 1β· []
cons branch x (y 1β· ys) = branch 1 x y 2β· ys
cons branch x (y 2β· ys) = x 1β· cons (branch β double) y ys
array-foldr : (N : β β Type t) β (β n m β N (2^ n * 1) β N (2^ n * m) β N (2^ n * suc m)) β N 0 β Array N ns β N β¦ ns ββ§
array-foldr {ns = 0α΅} N c b [] = b
array-foldr {ns = 2α΅ ns} N c b (x 2β· xs) = c 1 β¦ ns ββ§ x (array-foldr (N β double) (c β suc) b xs)
array-foldr {ns = 1α΅ ns} N c b (x 1β· xs) = c 0 (β¦ ns ββ§ * 2) x (array-foldr (N β double) (c β suc) b xs)
open import Data.Vec
import Data.Nat.Properties as β
doubleβ‘*2 : β n β n + n β‘ n * 2
doubleβ‘*2 zero = refl
doubleβ‘*2 (suc n) = cong suc (β.+-suc n n ΝΎ cong suc (doubleβ‘*2 n))
module NonNorm {t} (N : β β Type t) (f : β p n m β N (2^ p * n) β N (2^ p * m) β N (2^ p * (n + m))) (z : N 0) where
spine : Vec (N 1) n β Array (N ) β¦ n ββ§
spine [] = []
spine (x β· xs) = cons (Ξ» n x y β subst N (doubleβ‘*2 n) (f 0 n n x y)) x (spine xs)
unspine : Array N ns β N β¦ ns ββ§
unspine = array-foldr N (Ξ» n β f n 1) z
treeFold : Vec (N 1) n β N n
treeFold xs = subst N (ββπΉββ _) (unspine (spine xs))
pow-suc : β n m β (2^ n * 1) + (2^ n * m) β‘ (2^ n * suc m)
pow-suc zero m = refl
pow-suc (suc n) m = sym (β.+-*-distrib (2^ n * 1) (2^ n * m) 2) ΝΎ cong (_* 2) (pow-suc n m)
module _ {t} (N : β β Type t) (f : β {n m} β N n β N m β N (n + m)) (z : N 0) where
spine : Vec (N 1) n β Array (N ) β¦ n ββ§
spine [] = []
spine (x β· xs) = cons (Ξ» n x y β subst N (doubleβ‘*2 n) (f x y)) x (spine xs)
unspine : Array N ns β N β¦ ns ββ§
unspine = array-foldr N (Ξ» n m xs ys β subst N (pow-suc n m) (f xs ys)) z
treeFold : Vec (N 1) n β N n
treeFold xs = subst N (ββπΉββ _) (unspine (spine xs))