\begin{code}
{-# OPTIONS --safe #-}
open import Signatures
open import Prelude hiding (Iso)
module FreeMonad.Syntax (π½ : Signature) where
open Signature π½
data Syntax (A : Type a) : Type a
data Syntax Ξ½ where
var : Ξ½ β Syntax Ξ½
op : β¦ π½ β§ (Syntax Ξ½) β Syntax Ξ½
\end{code}
%<*op-con>
\begin{code}
Opβ¦_β§ : β o β Syntax (Arity o)
Op⦠o ⧠= op (o , var)
\end{code}
%</op-con>
\begin{code}
private variable Ξ½ : Type a
\end{code}
%<*syntax-alg>
\begin{code}
syntax-alg : π½ -Alg[ Syntax Ξ½ ]
syntax-alg = op
\end{code}
%</syntax-alg>
\begin{code}
syntax-alg' : (v : Type) β π½ -Alg
syntax-alg' Ξ½ = Syntax Ξ½ , op
private variable π : Type c
\end{code}
%<*interp>
\begin{code}[number=syn:interp]
interp : π½ -Alg[ π ] β (Ξ½ β π) β Syntax Ξ½ β π
interp Ο Ο (var x) = Ο x
interp Ο Ο (op (Oα΅’ , k)) = Ο (Oα΅’ , Ξ» i β interp Ο Ο (k i))
\end{code}
%</interp>
\begin{code}
data ππΆπ«π±ππ΅ (A : Type a) (B : Type b) (P : B β Type c) : Type (a ββ b ββ c) where
var : A β ππΆπ«π±ππ΅ A B P
op : (xs : β¦ π½ β§ B)
(Pβ¨xsβ© : β i β P (xs .snd i)) β ππΆπ«π±ππ΅ A B P
βͺ_β« : ππΆπ«π±ππ΅ A (Syntax A) P β Syntax A
βͺ var x β« = var x
βͺ op xs _ β« = op xs
DepAlg : (A : Type a) β (Syntax A β Type b) β Type (a ββ b)
DepAlg A P = (xs : ππΆπ«π±ππ΅ A (Syntax A) P) β P βͺ xs β«
syntax DepAlg A (Ξ» xs β P) = Ξ¨[ xs β¦ Syntax A ] P
elim-s : (P : Syntax A β Type b) β DepAlg A P β (xs : Syntax A) β P xs
elim-s _ alg (var x) = alg (var x)
elim-s P alg (op (Op , xs)) = alg (op (Op , xs) (Ξ» i β elim-s P alg (xs i)))
module SyntaxBind where
return : A β Syntax A
return = var
private variable
Ξ½β² : Type b
infixl 4.5 _=<<_
_=<<_ : (Ξ½ β Syntax Ξ½β²) β Syntax Ξ½ β Syntax Ξ½β²
_=<<_ = interp op
infixr 4.5 _>>=_
\end{code}
%<*bind>
\begin{code}
_>>=_ : Syntax A β (A β Syntax B) β Syntax B
xs >>= Ο = interp op Ο xs
\end{code}
%</bind>
\begin{code}
infixr 4.5 _>>_
_>>_ : Syntax A β Syntax B β Syntax B
xs >> ys = xs >>= Ξ» _ β ys
infixr 9 _<=<_
_<=<_ : (B β Syntax C) β (A β Syntax B) β A β Syntax C
(f <=< g) x = f =<< g x
infixl 9 _>=>_
_>=>_ : (A β Syntax B) β (B β Syntax C) β A β Syntax C
_>=>_ = flip _<=<_
infixr 4.5 _<$>_
_<$>_ : (A β B) β Syntax A β Syntax B
f <$> xs = xs >>= var β f
infixl 4.5 _<&>_
_<&>_ : Syntax A β (A β B) β Syntax B
xs <&> f = f <$> xs
<$>-comp : (xs : Syntax A) β (f : A β B) β (g : B β C) β ((g β f) <$> xs) β‘ (g <$> (f <$> xs))
<$>-comp (var x) f g = refl
<$>-comp (op (o , k)) f g i = op (o , Ξ» a β <$>-comp (k a) f g i)
open SyntaxBind
interp-id :
\end{code}
%<*interp-id>
\begin{code}
(xs : Syntax Ξ½) β interp op var xs β‘ xs
\end{code}
%</interp-id>
\begin{code}
interp-id (var x) = refl
interp-id (op (Oα΅’ , k)) = cong (op β _,_ Oα΅’) (funExt Ξ» i β interp-id (k i))
interp-fusion : (f : C β A) {gβ : β¦ π½ β§ C β C} {gβ : β¦ π½ β§ A β A} (c : B β C) β
(β xs β f (gβ xs) β‘ gβ (cmap f xs)) β
β xs β f (interp gβ c xs) β‘ interp gβ (f β c) xs
interp-fusion f c p (var x) = refl
interp-fusion f {gβ = gβ} c p (op (Oα΅’ , xs) ) =
p _ ΝΎ cong gβ (cong (Oα΅’ ,_) (funExt Ξ» x β interp-fusion f c p (xs x)))
private module DisplayComp where
private variable Ξ½β² : Type b
interp-comp : β (Ο : π½ -Alg[ π ]) (Ο : Ξ½β² β π) (k : Ξ½ β Syntax Ξ½β²) xs β
\end{code}
%<*interp-comp>
\begin{code}[number=interp-comp]
interp Ο Ο (xs >>= k) β‘ interp Ο (interp Ο Ο β k) xs
\end{code}
%</interp-comp>
\begin{code}
interp-comp Ο Ο k (var x) = refl
interp-comp Ο Ο k (op (Oα΅’ , ks)) = cong (Ο β _,_ Oα΅’) (funExt Ξ» i β interp-comp Ο Ο k (ks i))
interp-comp : β (f : β¦ π½ β§ A β A) (k : B β A) (c : C β Syntax B) xs β
interp f k (xs >>= c) β‘ interp f (interp f k β c) xs
interp-comp f k c = interp-fusion (interp f k) c Ξ» _ β refl
interp-homo : β {Ξ½ C : Type} β (alg : π½ -Alg[ C ]) β (Ξ½ β C)
β ((Syntax Ξ½ , syntax-alg) βΆ (C , alg))
interp-homo {Ξ½ = Ξ½} alg k = interp alg k , funExt comm
where
comm : (x : β¦ π½ β§ (Syntax Ξ½)) β interp alg k (op x) β‘ alg (cmap (interp alg k) x)
comm (o , xs) = refl
var-alg : (Ξ½ : Type) β (C : Type) β (alg : π½ -Alg[ C ])
β ((Syntax Ξ½ , syntax-alg {Ξ½ = Ξ½}) βΆ (C , alg)) β Ξ½ β C
var-alg Ξ½ C alg (h , _) x = h (var x)
open import Cubical.Foundations.Isomorphism using (isoToIsEquiv; Iso)
syntax-is-free : β {Ξ½ : Type} β (C : Type) β (alg : π½ -Alg[ C ])
β isEquiv (var-alg Ξ½ C alg)
syntax-is-free {Ξ½} C alg = isoToIsEquiv i where
i : Iso ((Syntax Ξ½ , syntax-alg {Ξ½ = Ξ½}) βΆ (C , alg)) (Ξ½ β C)
i .fun = var-alg Ξ½ C alg
i .inv k = interp-homo alg k
i .rightInv k = refl
i .leftInv (h , comm) = Ξ£PathP (h-path , comm-path) where
h-var-fusion-ty : Syntax Ξ½ β Type
h-var-fusion-ty x = interp alg (h β var) x β‘ h x
open import Cubical.Foundations.Prelude using (_ββ_ββ_)
open import Cubical.Foundations.Path using (PathPβ‘doubleCompPathΚ³)
h-var-fusion-alg : DepAlg Ξ½ h-var-fusion-ty
h-var-fusion-alg (var x) = refl
h-var-fusion-alg (op oxs Pβ¨xsβ©) = refl ββ p-IH ββ sym (Ξ» i β comm i oxs) where
p-IH : alg (oxs .fst , (Ξ» a β interp alg (Ξ» x β h (var x)) (oxs .snd a))) β‘ alg (cmap h oxs)
p-IH = cong (Ξ» xs' β alg (oxs .fst , xs')) (funExt (Ξ» a β Pβ¨xsβ© a))
h-var-fusion : β x β interp alg (h β var) x β‘ h x
h-var-fusion = elim-s h-var-fusion-ty h-var-fusion-alg
h-path : interp alg (h β var) β‘ h
h-path = funExt h-var-fusion
squeezeSquare : β{a}{A : Type a}{w x y z : A} (p : w β‘ x) {q : x β‘ y} (r : z β‘ y)
β (P : w β‘ z) β (sq : P β‘ p ββ q ββ sym r) β I β I β A
squeezeSquare p {q} r P sq i j = transport (sym (PathPβ‘doubleCompPathΚ³ p P q r)) sq i j
comm-path : PathP (Ξ» i β (Ξ» xs β h-path i (op xs)) β‘ (Ξ» xs β alg (cmap (h-path i) xs)))
(interp-homo alg (h β var) .snd)
comm
comm-path i j oxs = squeezeSquare (Ξ» k β (interp-homo alg (h β var) .snd) k oxs )
(Ξ» k β comm k oxs)
(h-var-fusion (op oxs))
(refl {x = h-var-fusion (op oxs)})
j
i
ββ² : β {p} β (A β Type p) β Syntax A β Type p
ββ² P (var x) = P x
ββ² P (op (O , xs)) = β i Γ ββ² P (xs i)
β‘β² : β {p} β (A β Type p) β Syntax A β Type p
β‘β² P (var x) = P x
β‘β² P (op (O , xs)) = β i β β‘β² P (xs i)
β‘β²->>=-β‘β² : β {p q} (P : A β Type p) (Q : B β Type q) β
(xs : Syntax A) (f : A β Syntax B) β
(β x β P x β β‘β² Q (f x)) β β‘β² P xs β β‘β² Q (xs >>= f)
β‘β²->>=-β‘β² P Q (var x) f t Pxs = t x Pxs
β‘β²->>=-β‘β² P Q (op (Oα΅’ , xs)) f t Pxs i = β‘β²->>=-β‘β² P Q (xs i) f t (Pxs i)
ββ²->>=-ββ² : β {p q} (P : A β Type p) (Q : B β Type q) β
(xs : Syntax A) (f : A β Syntax B) β
(β x β P x β ββ² Q (f x)) β ββ² P xs β ββ² Q (xs >>= f)
ββ²->>=-ββ² P Q (var x) f t Pxs = t x Pxs
ββ²->>=-ββ² P Q (op (Oα΅’ , xs)) f t (i , Pxs) = i , ββ²->>=-ββ² P Q (xs i) f t Pxs
β‘β²-fmap : β {A : Type a} {P Q : A β Type p} (t : Syntax A) β
(β (x : A) β P x β Q x) β (β‘β² P t β β‘β² Q t)
β‘β²-fmap (var x) f p = f x p
β‘β²-fmap (op (o , k)) f p = Ξ» a β β‘β²-fmap (k a) f (p a)
ββ²-fmap : β {A : Type a} {P Q : A β Type p} (t : Syntax A) β
(β (x : A) β P x β Q x) β (ββ² P t β ββ² Q t)
ββ²-fmap (var x) f p = f x p
ββ²-fmap (op (o , k)) f (a , p) = a , ββ²-fmap (k a) f p
β‘β²-shift : β {A : Type a} {P : B β Type p} β (f : A β B) β (t : Syntax A) β β‘β² (P β f) t β β‘β² P (f <$> t)
β‘β²-shift f (var x) p = p
β‘β²-shift f (op (o , k)) p a = β‘β²-shift f (k a) (p a)
ββ²-shift : β {A : Type a} {P : B β Type p} β (f : A β B) β (t : Syntax A) β ββ² (P β f) t β ββ² P (f <$> t)
ββ²-shift f (var x) p = p
ββ²-shift f (op (o , k)) (a , p) = a , ββ²-shift f (k a) p
var-inj : Injective (Syntax.var {A = A})
var-inj {x = x} {y} = cong Ξ» { (var x) β x ; (op _) β x }
op-inj : Injective (Syntax.op {A = A})
op-inj {x = x} {y} = cong Ξ» { (var _) β x ; (op x) β x }
open import Cubical.Data.Sigma.Properties
opF-inj : isSet Op β (O : Op) β (xs ys : Arity O β Syntax A) β (op (O , xs) β¦ Syntax A) β‘ op (O , ys) β xs β‘ ys
opF-inj set O xs ys p =
Ξ£-contractFst (refl , Ξ» _ β set _ _ _ _) .fst (PathPΞ£ (op-inj p))
isReturn : Syntax A β Bool
isReturn (var _) = true
isReturn (op _) = false
fmap-injective : (f : A β B) β Injective f β Injective (f <$>_)
fmap-injective f inj {var x} {var y} p = cong var (inj (var-inj p))
fmap-injective {A = A} {B = B} f inj {op (i , x)} {op (j , y)} p =
let q = op-inj { x = i , _<$>_ f β x } { y = j , _<$>_ f β y } p
h = cong fst q
in cong (op β¦ (β¦ π½ β§ (Syntax _) β Syntax _))
(congβ _,_ h
(J (Ξ» z zp β β y β PathP (Ξ» l β Arity (zp l) β Syntax B) (_<$>_ f β x) (_<$>_ f β y) β PathP (Ξ» l β Arity (zp l) β Syntax A) x y)
(Ξ» yβ² pβ² β funExt Ξ» k β fmap-injective f inj {x k} {yβ² k} (cong (_$ k) pβ²)) h y (cong snd q)))
fmap-injective f inj {var x} {op y} p = absurd (trueβ’false (cong isReturn p))
fmap-injective f inj {op x} {var y} p = absurd (falseβ’true (cong isReturn p))
varβ’op : β {x : A} {O k} β var x β’ op (O , k)
varβ’op = trueβ’false β cong isReturn
opβ’var : β {x : A} {O k} β op (O , k) β’ var x
opβ’var = falseβ’true β cong isReturn
>>=-com-<$> : (f : A β Syntax B) (g : B β C) (xs : Syntax A) β (xs >>= Ξ» x β g <$> f x) β‘ g <$> (xs >>= f)
>>=-com-<$> f g = elim-s _ Ξ» { (var x) β refl ; (op (O , k) Pβ¨xsβ©) β cong (op β _,_ O) (funExt Pβ¨xsβ©) }
\end{code}