agda2hs-1.4: lib/base/Haskell/Law/Applicative/FromMonad.agda
module Haskell.Law.Applicative.FromMonad where
open import Haskell.Prim
open import Haskell.Prim.Applicative
open import Haskell.Prim.Functor
open import Haskell.Prim.Monad
open import Haskell.Law.Applicative.Def
open import Haskell.Law.Monad.Def as Monad
open import Haskell.Law.Equality
open import Haskell.Law.Functor
open import Haskell.Law.Functor.FromMonad
-------------------------------------------------------------------------------
-- Prove the Applicative laws from the Monad laws
--
prop-PreLawfulMonad→IsLawfulApplicative
: ∀ ⦃ _ : Monad m ⦄ ⦃ _ : PreLawfulMonad m ⦄
→ IsLawfulApplicative m
--
prop-PreLawfulMonad→IsLawfulApplicative {m} = record
{ super = prop-PreLawfulMonad→IsLawfulFunctor
; identity = midentity
; composition = mcomposition
; homomorphism = mhomomorphism
; interchange = minterchange
; functor = mfunctor
}
where
midentity : ∀ {a} (ma : m a) → (pure id <*> ma) ≡ ma
midentity {a} ma
rewrite def-pure-return (id {a})
| def-<*>->>= (return id) ma
= begin
return id >>= (λ f → ma >>= (λ x → return (f x)))
≡⟨ Monad.leftIdentity _ _ ⟩
ma >>= (λ x → return (id x))
≡⟨ Monad.rightIdentity _ ⟩
ma
∎
mfunctor : ∀ {a b} (f : a → b) (u : m a) → fmap f u ≡ (pure f <*> u)
mfunctor f u = begin
fmap f u
≡⟨ Monad.def-fmap->>= _ _ ⟩
(do x ← u; return (f x))
≡⟨ sym (Monad.leftIdentity _ _) ⟩
(do f' ← return f; x ← u; return (f' x))
≡⟨ cong (λ o → o >>= _) (sym (def-pure-return _)) ⟩
(do f' ← pure f; x ← u; return (f' x))
≡⟨ sym (def-<*>->>= _ _) ⟩
pure f <*> u
∎
mcomposition
: ∀ {a b c} (u : m (b → c)) (v : m (a → b)) (w : m a)
→ (pure _∘_ <*> u <*> v <*> w) ≡ (u <*> (v <*> w))
mcomposition u v w
= begin
pure _∘_ <*> u <*> v <*> w
≡⟨ cong (λ o → o <*> u <*> v <*> w) (def-pure-return _∘_) ⟩
return _∘_ <*> u <*> v <*> w
≡⟨ cong (λ o → o <*> v <*> w) (def-<*>->>= _ _ ) ⟩
(do comp ← return _∘_; g ← u; return (comp g)) <*> v <*> w
≡⟨ cong (λ o → o <*> v <*> w) (Monad.leftIdentity _ _) ⟩
(do g ← u; return (_∘_ g)) <*> v <*> w
≡⟨ cong (λ o → o <*> w) (def-<*>->>= _ _ ) ⟩
(do g' ← (do g ← u; return (_∘_ g)); f ← v; return (g' f)) <*> w
≡⟨ cong (λ o → o <*> w) (sym (Monad.associativity u _ _)) ⟩
(do g ← u; g' ← return (_∘_ g); f ← v; return (g' f)) <*> w
≡⟨ cong (λ o → o <*> w) (cong-monad u (λ g → Monad.leftIdentity _ _)) ⟩
(do g ← u; f ← v; return (g ∘ f)) <*> w
≡⟨ def-<*>->>= _ _ ⟩
(do gf ← (do g ← u; f ← v; return (g ∘ f)); x ← w; return (gf x))
≡⟨ sym (Monad.associativity u _ _) ⟩
(do g ← u; gf ← (do f ← v; return (g ∘ f)); x ← w; return (gf x))
≡⟨ cong-monad u (λ g → sym (Monad.associativity v _ _)) ⟩
(do g ← u; do f ← v; gf ← return (g ∘ f); x ← w; return (gf x))
≡⟨ cong-monad u (λ g → cong-monad v (λ f → Monad.leftIdentity _ _)) ⟩
(do g ← u; f ← v; x ← w; return (g (f x)))
≡⟨ cong-monad u (λ g → cong-monad v λ f → cong-monad w (λ x → sym (Monad.leftIdentity _ _))) ⟩
(do g ← u; f ← v; x ← w; y ← return (f x); return (g y))
≡⟨ cong-monad u (λ g → cong-monad v λ x → Monad.associativity _ _ _) ⟩
(do g ← u; f ← v; y ← (do x ← w; return (f x)); return (g y))
≡⟨ cong-monad u (λ g → Monad.associativity _ _ _) ⟩
(do g ← u; y ← (do f ← v; x ← w; return (f x)); return (g y))
≡⟨ sym (def-<*>->>= _ _) ⟩
u <*> (do f ← v; x ← w; return (f x))
≡⟨ cong (λ o → u <*> o) (sym (def-<*>->>= _ _)) ⟩
u <*> (v <*> w)
∎
mhomomorphism
: ∀ {a b} (f : a → b) (x : a)
→ (pure {m} f <*> pure x) ≡ pure (f x)
mhomomorphism f x = begin
pure {m} f <*> pure x
≡⟨ cong₂ (_<*>_) (def-pure-return f) (def-pure-return x) ⟩
return {m} f <*> return x
≡⟨ def-<*>->>= _ _ ⟩
(do f' ← return f; x' ← return x; return (f' x'))
≡⟨ Monad.leftIdentity _ _ ⟩
(do x' ← return x; return (f x'))
≡⟨ Monad.leftIdentity _ _ ⟩
return (f x)
≡⟨ sym (def-pure-return _) ⟩
pure (f x)
∎
minterchange
: ∀ {a b} (u : m (a → b)) (y : a)
→ (u <*> pure y) ≡ (pure (_$ y) <*> u)
minterchange u y = begin
u <*> pure y
≡⟨ cong (u <*>_) (def-pure-return _) ⟩
u <*> return y
≡⟨ def-<*>->>= _ _ ⟩
(do f ← u; y' ← return y; return (f y'))
≡⟨ cong-monad u (λ f → Monad.leftIdentity y _) ⟩
(do f ← u; return (f y))
≡⟨ sym (Monad.leftIdentity _ _) ⟩
(do y'' ← return (_$ y); f ← u; return (y'' f))
≡⟨ sym (def-<*>->>= _ _) ⟩
return (_$ y) <*> u
≡⟨ sym (cong (_<*> u) (def-pure-return _)) ⟩
pure (_$ y) <*> u
∎