{-# OPTIONS --allow-unsolved-metas #-} open import Prelude open import Algebra open import Algebra.Monus module Codata.Heap {ℓ} {𝑆 : Type ℓ} (mon : CTMAPOM 𝑆) where open CTMAPOM mon open import Data.List private variable i j : 𝑆 data Heap′ {a} (i : 𝑆) (A : Type a) : Type (a ℓ⊔ ℓ) where heap : A → ∀ w → -- Segment size ( (w<i : w < i) → List (Heap′ (i ∸ w) A) ) → Heap′ i A Heap : Type a → Type (a ℓ⊔ ℓ) Heap A = ∀ {i} → Heap′ i A extract : Heap′ i A → A extract (heap x _ _) = x duplicate : Heap′ (i ∙ j) A → Heap′ i (Heap′ j A) duplicate h@(heap x w xs) = heap {!!} w λ p → let q = map duplicate (subst (List ∘′ flip Heap′ _) {!!} (xs ({!!}))) in {!!} -- -------------------------------------------------------------------------------- -- -- Empty colists -- -------------------------------------------------------------------------------- -- -- To terminate computation you use all the fuel, making an empty list. -- -- (I'm not sure how principled this is: semantically I don't know if I like -- -- that the size of a segment can depend on the supplied size parameter). -- empty : Heap A -- empty {i = i} = i ◃ λ i<i → ⊥-elim (irrefl i<i) -- -- -------------------------------------------------------------------------------- -- -- -- Finite derived colists -- -- -------------------------------------------------------------------------------- -- -- -- singleton -- -- pure : A → Heap A -- -- pure x = x ∹ empty -- -- replicate : ℕ → A → Heap A -- -- replicate zero x = empty -- -- replicate (suc n) x = x ∹ replicate n x -- -- -------------------------------------------------------------------------------- -- -- -- Infinite colists -- -- -------------------------------------------------------------------------------- -- -- -- This unfold function produces an infinite list; it needs every size segment -- -- -- be non empty so that each step uses some fuel. This is what provides the -- -- -- termination argument. -- -- module _ -- -- (B : 𝑆 → Type b) -- The seed type -- -- (ϕ : ∀ {i} → -- At depth i -- -- B i → -- With this seed -- -- ∃ w × -- Produce a segment of size w -- -- (w ≢ ε) × -- w can't be ε, so that we use some of the fuel to prove -- -- -- termination -- -- ((w<i : w < i) → A × B (i ∸ w)) -- And produce the cons constructor. -- -- ) -- -- -- ^ The step function -- -- where -- -- unfold′ : Acc _<_ i → B i → Heap′ A i -- -- unfold′ a = uncurry _◃_ -- -- ∘ map₂ -- -- (λ { (w≢ε , xs′) w<i → -- -- map₂ (case a of -- -- λ { (acc wf) → -- -- unfold′ (wf _ (∸‿<-< _ _ w<i w≢ε)) }) -- -- (xs′ w<i) }) -- -- ∘ ϕ -- -- unfold : (fdc : WellFounded _<_) -- -- (B : 𝑆 → Type b) -- -- (ϕ : ∀ {i} → B i → ∃ w × (w ≢ ε) × ((w<i : w < i) → A × B (i ∸ w))) → -- -- (∀ {i} → B i) → Heap A -- -- unfold fdc B ϕ xs {i} = unfold′ B ϕ (fdc i) xs -- -- -- Here's a simple example using the unfold function: this produces infinitely -- -- -- repeated values, with segment size s. -- -- repeat : (fdc : WellFounded _<_) (s : 𝑆) (s≢ε : s ≢ ε) (x : A) → Heap A -- -- repeat fdc s s≢ε x = unfold fdc (const ⊤) (λ _ → s , s≢ε , const (x , tt)) tt -- -- -------------------------------------------------------------------------------- -- -- -- Manipulating colists -- -- -------------------------------------------------------------------------------- -- -- -- One important thing to note about the Heap type: it is inductive! -- -- -- Although it does technically represent "coinduction", the constructors and -- -- -- type itself are inductive as far as Agda can see. For that reason functions -- -- -- like map pass the termination checker with no extra ceremony. -- -- map : (A → B) → Heap′ A i → Heap′ B i -- -- map f (w ◃ xs) = w ◃ λ w<i → case xs w<i of λ { (y , ys) → f y , map f ys } -- -- -- You can extract a finite prefix of the colist. -- -- open import Data.List using (List; _∷_; []) -- -- take′ : ∀ i → Heap′ A i → List A -- -- take′ i (w ◃ xs) with w <? i -- -- ... | no _ = [] -- -- ... | yes w<i with xs w<i -- -- ... | y , ys = y ∷ take′ _ ys -- -- take : 𝑆 → Heap A → List A -- -- take x xs = take′ x xs