{-# OPTIONS --allow-unsolved-metas #-}
module Control.Monad.Freer where
open import Prelude
open import Data.List hiding (map)
open import Data.List.Properties
open import Data.List.Membership
open import Algebra
open import Data.Fin hiding (fs)
open import Container
Distributes : (Type a → Type a) → (Type a → Type a) → Type _
Distributes F G = ∀ {A} → F (G A) → G (F A)
Freer : List Container → Type₁ → Type₁
Freer fs A = foldr ⟦_⟧ A fs
private
variable f g : Container
variable fs gs : List Container
bind : Freer fs A → (A → Freer gs B) → Freer (fs ++ gs) B
bind {fs = []} xs k = k xs
bind {fs = f ∷ fs} xs k = cmap (flip (bind {fs = fs}) k) xs
join : Freer fs (Freer gs A) → Freer (fs ++ gs) A
join {fs = []} = id
join {fs = f ∷ fs} = cmap (join {fs = fs})
extend : Freer (fs ++ gs) A → (Freer gs A → B) → Freer fs B
extend {fs = []} x k = (k x)
extend {fs = f ∷ fs} xs k = cmap (flip (extend {fs = fs}) k) xs
module _ {𝐹 : Type₁ → Type₁}(mon : Monad 𝐹) where
open import Data.Fin.Properties using (_<_)
open Monad mon
handle : (i : Fin (length fs)) →
(⟦ fs ! i ⟧ ⇒ 𝐹) →
(∀ j → j < i → Distributes ⟦ fs ! j ⟧ 𝐹) →
Freer fs A →
𝐹 (Freer (delete fs i) A)
handle {fs = f ∷ fs} nothing h d xs = h xs
handle {fs = f ∷ fs} (just i) h d xs = d nothing tt (cmap (handle {fs = fs} i h (d ∘ just)) xs)
handle″ : (∀ j → Distributes 𝐹 ⟦ fs ! j ⟧) →
𝐹 (Freer fs A) →
Freer fs (𝐹 A)
handle″ {fs = []} d xs = xs
handle″ {fs = f ∷ fs} d xs = cmap (handle″ {fs = fs} (d ∘ just)) (d f0 xs)
handle′ : (i : Fin (length fs)) →
(⟦ fs ! i ⟧ ⇒ 𝐹) →
(∀ j → i < j → Distributes 𝐹 ⟦ fs ! j ⟧) →
Freer fs A →
Freer (delete fs i) (𝐹 A)
handle′ {fs = f ∷ fs} (just i) h d xs = cmap (handle′ {fs = fs} i h (d ∘ just)) xs
handle′ {fs = f ∷ fs} nothing h d xs = handle″ {fs = fs} (λ j → d (just j) tt) (h xs)