{-# OPTIONS --rewriting #-} module Examples.Decalf.GlobalState where open import Algebra.Cost costMonoid = ℕ-CostMonoid open CostMonoid costMonoid using (ℂ) open import Calf costMonoid open import Calf.Data.Nat as Nat using (nat; _*_) open import Calf.Data.Equality as Eq using (_≡_; module ≡-Reasoning) open import Function S : tp⁺ S = nat variable s s₁ s₂ : val S postulate get : (X : tp⁻) → (val S → cmp X) → cmp X set : (X : tp⁻) → val S → cmp X → cmp X get/get : {e : val S → val S → cmp X} → (get X λ s₁ → get X λ s₂ → e s₁ s₂) ≡ (get X λ s → e s s) get/set : {e : cmp X} → (get X λ s → set X s e) ≡ e set/get : {e : val S → cmp X} → set X s (get X e) ≡ set X s (e s) set/set : {e : cmp X} → set X s₁ (set X s₂ e) ≡ set X s₂ e get/step : (c : ℂ) {e : val S → cmp X} → step X c (get X e) ≡ get X λ s → step X c (e s) set/step : (c : ℂ) {e : cmp X} → step X c (set X s e) ≡ set X s (step X c e) module StateDependentCost where open import Examples.Decalf.Basic e : cmp (F nat) e = get (F nat) λ n → bind (F nat) (double n) λ n' → set (F nat) n' $ ret n e/bound : cmp (F nat) e/bound = get (F nat) λ n → set (F nat) (2 * n) $ step (F nat) n $ ret n e/has-cost : e ≡ e/bound e/has-cost = Eq.cong (get (F nat)) $ funext λ n → let open ≡-Reasoning in begin ( bind (F nat) (double n) λ n' → set (F nat) n' $ ret n ) ≡⟨ Eq.cong (λ e₁ → bind (F nat) e₁ λ n' → set (F nat) n' (ret n)) (double/has-cost n) ⟩ ( bind (F nat) (step (F nat) n (ret (2 * n))) λ n' → set (F nat) n' $ ret n ) ≡⟨⟩ ( step (F nat) n $ set (F nat) (2 * n) $ ret n ) ≡⟨ set/step n ⟩ ( set (F nat) (2 * n) $ step (F nat) n $ ret n ) ∎