{-# OPTIONS --exact-split #-}
{-# OPTIONS --no-sized-types #-}
{-# OPTIONS --no-universe-polymorphism #-}
{-# OPTIONS --without-K #-}
module FOTC.Program.MapIterate.MapIterateI where
open import Common.FOL.Relation.Binary.EqReasoning
open import FOTC.Base
open import FOTC.Base.List
open import FOTC.Data.List
open import FOTC.Data.List.PropertiesI
open import FOTC.Data.Stream.Type
open import FOTC.Relation.Binary.Bisimilarity.Type
unfoldMapIterate : ∀ f x →
map f (iterate f x) ≡ f · x ∷ map f (iterate f (f · x))
unfoldMapIterate f x =
map f (iterate f x) ≡⟨ mapCong₂ (iterate-eq f x) ⟩
map f (x ∷ iterate f (f · x)) ≡⟨ map-∷ f x (iterate f (f · x)) ⟩
f · x ∷ map f (iterate f (f · x)) ∎
map-iterate-Stream : ∀ f x → Stream (map f (iterate f x))
map-iterate-Stream f x = Stream-coind A h (x , refl)
where
A : D → Set
A xs = ∃[ y ] xs ≡ map f (iterate f y)
h : ∀ {xs} → A xs → ∃[ x' ] ∃[ xs' ] xs ≡ x' ∷ xs' ∧ A xs'
h (y , prf) = f · y
, map f (iterate f (f · y))
, trans prf (unfoldMapIterate f y)
, f · y , refl
iterate-Stream : ∀ f x → Stream (iterate f (f · x))
iterate-Stream f x = Stream-coind A h (x , refl)
where
A : D → Set
A xs = ∃[ y ] xs ≡ iterate f (f · y)
h : ∀ {xs} → A xs → ∃[ x' ] ∃[ xs' ] xs ≡ x' ∷ xs' ∧ A xs'
h (y , prf) = f · y
, iterate f (f · (f · y))
, trans prf (iterate-eq f (f · y))
, f · y , refl
≈-map-iterate : ∀ f x → map f (iterate f x) ≈ iterate f (f · x)
≈-map-iterate f x = ≈-coind B h (x , refl , refl)
where
B : D → D → Set
B xs ys = ∃[ y ] xs ≡ map f (iterate f y) ∧ ys ≡ iterate f (f · y)
h : ∀ {xs} {ys} → B xs ys →
∃[ x' ] ∃[ xs' ] ∃[ ys' ] xs ≡ x' ∷ xs' ∧ ys ≡ x' ∷ ys' ∧ B xs' ys'
h (y , prf₁ , prf₂) =
f · y
, map f (iterate f (f · y))
, iterate f (f · (f · y))
, trans prf₁ (unfoldMapIterate f y)
, trans prf₂ (iterate-eq f (f · y))
, ((f · y) , refl , refl)