module Monad where
open import Level
open import Data.Unit hiding (setoid)
open import Data.Product
open import Relation.Binary
open import Relation.Binary.PropositionalEquality
hiding ( setoid ; isEquivalence )
renaming ( trans to trans≡ ; sym to sym≡ ; cong to cong≡ ; cong₂ to cong₂≡ )
[http://www.disi.unige.it/person/MoggiE/ftp/ic91.pdf]
[http://homepages.inf.ed.ac.uk/wadler/papers/essence/essence.ps]
[https://www.era.lib.ed.ac.uk/bitstream/1842/196/1/Comp_Eff_Monads.pdf]
[http://ncatlab.org/nlab/show/Lawvere+theory]
[https://hackage.haskell.org/package/Frank]
[http://math.andrej.com/eff/]
[http://www.pps.univ-paris-diderot.fr/~mellies/papers/segal-lics-2010.pdf]
module StateMonad (S : Set) where
data ΣState (X : Set) : Set where
`get : (S → X) → ΣState X
`set : S × X → ΣState X
data ΣGet (X : Set) : Set where
`get : (S → X) → ΣGet X
data ΣSet (X : Set) : Set where
`set : S × X → ΣSet X
data _⊕_ (F G : Set → Set)(X : Set) : Set where
inl : F X → (F ⊕ G) X
inr : G X → (F ⊕ G) X
data StateF (V : Set) : Set where
return : V → StateF V
op : ΣState (StateF V) → StateF V
mutual
_>>=_ : ∀{V W} → StateF V → (V → StateF W) → StateF W
return x >>= mf = mf x
op fa >>= mf = op (ΣStatemap mf fa)
ΣStatemap : ∀{V W} → (V → StateF W) → ΣState (StateF V) → ΣState (StateF W)
ΣStatemap mf (`get k) = `get (λ s → (k s) >>= mf)
ΣStatemap mf (`set (s , k)) = `set (s , k >>= mf)
get : StateF S
get = op (`get λ s → return s)
set : S → StateF ⊤
set s = op (`set (s , return tt))
[http://ncatlab.org/nlab/show/free+monad]
[https://www.fpcomplete.com/user/dolio/many-roads-to-free-monads]
[http://blog.sigfpe.com/2014/04/the-monad-called-free.html]
[http://hackage.haskell.org/package/free-operational]
test0 : StateF S
test0 = get >>= λ s →
set s >>= λ _ →
get >>= λ s' →
return s'
test1 : StateF S
test1 = get >>= λ s' →
return s'
test2 : StateF S
test2 = get >>= λ s →
set s >>= λ _ →
return s
data _≃_ {V : Set} : StateF V → StateF V → Set where
get-get : ∀{k : S → S → StateF V} →
(get >>= (λ s → get >>= λ s' → k s s' )) ≃ (get >>= λ s → k s s )
set-set : ∀{k s₁ s₂} →
(set s₁ >>= (λ _ → set s₂ >>= λ _ → k)) ≃ (set s₂ >>= λ _ → k)
get-set : ∀{k} →
(get >>= λ s → set s >>= λ _ → k) ≃ k
set-get : ∀{k s} →
(set s >>= (λ _ → get >>= k)) ≃ (set s >>= λ _ → k s)
[http://matija.pretnar.info/pdf/the-logic-and-handling-of-algebraic-effects.pdf]
data _∼_ {V : Set} : StateF V → StateF V → Set₁ where
inc : ∀{p q} → p ≃ q → p ∼ q
trans : ∀{p q r} → p ∼ q → q ∼ r → p ∼ r
refl : ∀{p} → p ∼ p
sym : ∀{p q} → p ∼ q → q ∼ p
cong : ∀{W}(tm : StateF W){ps qs : W → StateF V} →
(∀ w → ps w ∼ qs w) →
(tm >>= ps) ∼ (tm >>= qs)
setoid : Set → Setoid _ _
setoid V = record
{ Carrier = StateF V
; _≈_ = _∼_
; isEquivalence = isEquivalence
}
where isEquivalence : ∀ {V : Set} → IsEquivalence (_∼_ {V = V})
isEquivalence = record
{ refl = refl
; sym = sym
; trans = trans
}
State : Set → Set
State X = ΣGet (ΣSet X)
eval : ∀{A} → StateF A → (S → S × A)
eval (return a) = λ s → (s , a)
eval (op (`get k)) = λ s → eval (k s) s
eval (op (`set (s' , k))) = λ s → eval k s'
reify : ∀{A} → (S → S × A) → State A
reify {A} f = `get λ s → `set (f s)
norm : ∀{A} → StateF A → State A
norm p = reify (eval p)
⌈_⌉ : ∀{A} → State A → StateF A
⌈ `get k ⌉ = get >>= λ s → help (k s)
where help : ∀ {A} → ΣSet A → StateF A
help (`set (s , v)) = set s >>= λ _ → return v
pf-sound : ∀{A} → (p : StateF A) → p ∼ ⌈ norm p ⌉
pf-complete : ∀ {A} {p q : StateF A} → p ∼ q → ∀{s} → eval p s ≡ eval q s
sound : ∀ {V} (p q : StateF V) → ⌈ norm p ⌉ ≡ ⌈ norm q ⌉ → p ∼ q
sound {V} p q r =
begin
p
≈⟨ pf-sound p ⟩
⌈ norm p ⌉
≡⟨ r ⟩
⌈ norm q ⌉
≈⟨ sym (pf-sound q) ⟩
q
∎
where open import Relation.Binary.EqReasoning (setoid V)
complete : ∀ {A} {p q : StateF A} → p ∼ q → ⌈ norm p ⌉ ≡ ⌈ norm q ⌉
complete {p = p} {q} r =
begin
⌈ norm p ⌉
≡⟨ refl ⟩
⌈ reify (eval p) ⌉
≡⟨ cong≡ (λ x → ⌈ reify x ⌉) (ext (λ z → pf-complete r)) ⟩
⌈ reify (eval q) ⌉
≡⟨ refl ⟩
⌈ norm q ⌉
∎
where open ≡-Reasoning
postulate ext : Extensionality zero zero
pf-sound (return x) = sym (inc get-set)
pf-sound {V} (op (`get k)) =
begin
op (`get k)
≡⟨ refl ⟩
get >>= k
≈⟨ cong (op (`get return))
(λ s' → pf-sound (k s')) ⟩
get >>= (λ s' → ⌈ norm (k s') ⌉)
≡⟨ refl ⟩
op (`get λ s' →
op (`get (λ s →
op (`set (proj₁ (eval (k s') s) ,
return (proj₂ (eval (k s') s)))))))
≈⟨ inc get-get ⟩
op (`get λ s →
op (`set (proj₁ (eval (k s) s) ,
return (proj₂ (eval (k s) s)))))
≡⟨ refl ⟩
⌈ norm (op (`get k)) ⌉
∎
where open import Relation.Binary.EqReasoning (setoid V)
pf-sound {V} (op (`set (s' , k))) =
begin
op (`set (s' , k ))
≈⟨ cong (op (`set (s' , return tt))) (λ _ → pf-sound k) ⟩
op (`set (s' , ⌈ norm k ⌉) )
≡⟨ refl ⟩
op (`set (s' ,
op (`get (λ s →
op (`set (proj₁ (eval k s),
return (proj₂ (eval k s))))))))
≈⟨ inc set-get ⟩
op (`set (s' ,
op (`set (proj₁ (eval k s'),
return (proj₂ (eval k s'))))))
≈⟨ inc set-set ⟩
op (`set (proj₁ (eval k s'),
return (proj₂ (eval k s'))))
≈⟨ sym (inc get-set) ⟩
op (`get λ s →
op (`set (s ,
op (`set (proj₁ (eval k s'),
return (proj₂ (eval k s')))))))
≈⟨ cong (get >>= return) (λ s → inc set-set) ⟩
op (`get λ s →
op (`set (proj₁ (eval k s'),
return (proj₂ (eval k s')))))
≡⟨ refl ⟩
⌈ norm (op (`set (s' , k))) ⌉
∎
where open import Relation.Binary.EqReasoning (setoid V)
eval-compose : ∀{A B}(tm : StateF A)(k : A → StateF B){s} →
eval (tm >>= k) s
≡ (let p : S × A
p = eval tm s in
eval (k (proj₂ p)) (proj₁ p))
eval-compose (return x) k = λ {s} → refl
eval-compose (op (`get x)) k = λ {s} → eval-compose (x s) k
eval-compose (op (`set (s' , x))) k = λ {s} → eval-compose x k
pf-complete (inc get-get) = refl
pf-complete (inc set-set) = refl
pf-complete (inc set-get) = refl
pf-complete (inc get-set) = refl
pf-complete {p = p}{q} (trans {q = r} r₁ r₂) = λ {s} →
begin
eval p s
≡⟨ pf-complete r₁ ⟩
eval r s
≡⟨ pf-complete r₂ ⟩
eval q s
∎
where open ≡-Reasoning
pf-complete refl = refl
pf-complete (sym r) = sym≡ (pf-complete r)
pf-complete (cong tm {ps}{qs} x) = λ {s} →
begin
eval (tm >>= ps) s
≡⟨ eval-compose tm ps ⟩
eval (ps (proj₂ (eval tm s))) (proj₁ (eval tm s))
≡⟨ pf-complete (x (proj₂ (eval tm s))) ⟩
eval (qs (proj₂ (eval tm s))) (proj₁ (eval tm s))
≡⟨ sym≡ (eval-compose tm qs) ⟩
eval (tm >>= qs) s
∎
where open ≡-Reasoning
test01 : test0 ∼ test1
test01 = sound test0 test1 refl
test12 : test1 ∼ test2
test12 = sound test1 test2 refl
cong₂ : ∀{V W}(tm tm' : StateF W){ps qs : W → StateF V} →
(tm ∼ tm') →
(∀ w → ps w ∼ qs w) →
(tm >>= ps) ∼ (tm' >>= qs)
norm-compose : ∀{V W}(tm : StateF W)(ps : W → StateF V) →
⌈ norm (tm >>= ps) ⌉ ≡ ⌈ norm (⌈ norm tm ⌉ >>= λ w → ⌈ norm (ps w) ⌉) ⌉
norm-compose tm ps =
begin
⌈ norm (tm >>= ps) ⌉
≡⟨ refl ⟩
op (`get (λ s →
op (`set (let p : S × _
p = eval (tm >>= ps) s in
proj₁ p , return (proj₂ p)))))
≡⟨ cong≡ (λ k → op (`get k)) (ext help) ⟩
op (`get (λ s →
(op (`set (let p₁ : S × _
p₁ = eval tm s
p₂ : S × _
p₂ = eval (ps (proj₂ p₁)) (proj₁ p₁) in
proj₁ p₂ , return (proj₂ p₂))))))
≡⟨ refl ⟩
⌈ norm (⌈ norm tm ⌉ >>= λ w → ⌈ norm (ps w) ⌉) ⌉
∎
where postulate ext : Extensionality zero zero
open ≡-Reasoning
help : (s : S) → (op (`set (let p : S × _
p = eval (tm >>= ps) s in
proj₁ p , return (proj₂ p))))
≡ (op (`set (let p₁ : S × _
p₁ = eval tm s
p₂ : S × _
p₂ = eval (ps (proj₂ p₁)) (proj₁ p₁) in
proj₁ p₂ , return (proj₂ p₂))))
help s = cong≡ (λ { (s , k) → op (`set (s , return k)) }) (eval-compose tm ps)
cong₂ {V} tm tm' {ps}{qs} q qp = sound (tm >>= ps) (tm' >>= qs)
(begin
⌈ norm (tm >>= ps) ⌉
≡⟨ norm-compose tm ps ⟩
⌈ norm (⌈ norm tm ⌉ >>= λ w → ⌈ norm (ps w) ⌉) ⌉
≡⟨ cong₂≡ (λ t k → ⌈ norm (t >>= k) ⌉)
(complete q)
(ext (λ w → complete (qp w))) ⟩
⌈ norm (⌈ norm tm' ⌉ >>= λ w → ⌈ norm (qs w) ⌉) ⌉
≡⟨ sym≡ (norm-compose tm' qs) ⟩
⌈ norm (tm' >>= qs) ⌉
∎)
where postulate ext : Extensionality zero zero
open ≡-Reasoning
open import Algebra
import Level
module Tick (M : Monoid Level.zero Level.zero) where
open Monoid M
R : Set
R = Carrier
data ΣTick (X : Set) : Set where
`tick : R × X → ΣTick X
data TickF (V : Set) : Set where
return : V → TickF V
op : ΣTick (TickF V) → TickF V
tick : R → TickF ⊤
tick r = op (`tick (r , return tt))
mutual
_>>=_ : ∀{A B} → TickF A → (A → TickF B) → TickF B
return x >>= mf = mf x
op fa >>= mf = op (ΣTickmap mf fa)
ΣTickmap : ∀{A B} → (A → TickF B) → ΣTick (TickF A) → ΣTick (TickF B)
ΣTickmap mf (`tick (r , k)) = `tick (r , k >>= mf)
data _≃_ {V : Set} : TickF V → TickF V → Set where
tick-eps : ∀{k : TickF V} →
(tick ε >>= λ _ → k) ≃ k
tick-com : ∀{k : TickF V}{r₁ r₂} →
(tick r₁ >>= λ _ →
tick r₂ >>= λ _ → k) ≃ (tick (r₁ ∙ r₂) >>= λ _ → k)
Tick : Set → Set
Tick X = ΣTick X
eval : ∀{A} → TickF A → R × A
eval (return a) = ε , a
eval {A} (op (`tick (r , k))) =
let p : R × A
p = eval k in
r ∙ (proj₁ p) , proj₂ p
reify : ∀{A} → R × A → Tick A
reify {A} (r , a) = `tick (r , a)
norm : ∀{A} → TickF A → Tick A
norm p = reify (eval p)
⌈_⌉ : ∀{A} → Tick A → TickF A
⌈ `tick (r , a) ⌉ = tick r >>= λ _ → return a
[http://homepages.inf.ed.ac.uk/s1225336/papers/mfps13.pdf]
[http://arxiv.org/abs/1312.1399]
[http://homepages.inf.ed.ac.uk/gdp/publications/Comb_Effects_Jour.pdf]