{-# 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))