Theory Lift_Monad

section ‹Lift monad›

theory Lift_Monad
imports Monad
begin

subsection ‹Type definition›

tycondef 'alifted = Lifted (lazy "'a")

lemma coerce_lifted_abs [simp]: "coerce(lifted_absx) = lifted_abs(coercex)"
apply (simp add: lifted_abs_def coerce_def)
apply (simp add: emb_prj_emb prj_emb_prj DEFL_eq_lifted)
done

lemma coerce_Lifted [simp]: "coerce(Liftedx) = Lifted(coercex)"
unfolding Lifted_def by simp

lemma fmapU_lifted_simps [simp]:
  "fmapUf(::udomlifted) = "
  "fmapUf(Liftedx) = Lifted(fx)"
unfolding fmapU_lifted_def lifted_map_def fix_const
apply simp
apply (simp add: Lifted_def)
done

subsection ‹Class instance proofs›

instance lifted :: "functor"
  by standard (induct_tac xs rule: lifted.induct, simp_all)

instantiation lifted :: monad
begin

fixrec bindU_lifted :: "udomlifted  (udom  udomlifted)  udomlifted"
  where "bindU_lifted(Liftedx)k = kx"

lemma bindU_lifted_strict [simp]: "bindUk = (::udomlifted)"
by fixrec_simp

definition returnU_lifted_def:
  "returnU = Lifted"

instance proof
  fix x :: "udom"
  fix f :: "udom  udom"
  fix h k :: "udom  udomlifted"
  fix xs :: "udomlifted"
  show "fmapUfxs = bindUxs(Λ x. returnU(fx))"
    by (induct xs rule: lifted.induct, simp_all add: returnU_lifted_def)
  show "bindU(returnUx)k = kx"
    by (simp add: returnU_lifted_def)
  show "bindU(bindUxsh)k = bindUxs(Λ x. bindU(hx)k)"
    by (induct xs rule: lifted.induct) simp_all
qed

end

subsection ‹Transfer properties to polymorphic versions›

lemma fmap_lifted_simps [simp]:
  "fmapf(::'alifted) = "
  "fmapf(Liftedx) = Lifted(fx)"
unfolding fmap_def by simp_all

lemma bind_lifted_simps [simp]:
  "bind(::'alifted)f = "
  "bind(Liftedx)f = fx"
unfolding bind_def by simp_all

lemma return_lifted_def: "return = Lifted"
unfolding return_def returnU_lifted_def
by (simp add: coerce_cfun cfcomp1 eta_cfun)

lemma join_lifted_simps [simp]:
  "join(::'aliftedlifted) = "
  "join(Liftedxs) = xs"
unfolding join_def by simp_all

end