Set Implicit Arguments.
Require list_utils.
Record Monoid: Type :=
{ monoid_type:> Set
; monoid_zero: monoid_type
; monoid_mult: monoid_type -> monoid_type -> monoid_type
; monoid_lunit: forall x, monoid_mult monoid_zero x = x
; monoid_runit: forall x, monoid_mult x monoid_zero = x
; monoid_assoc: forall x y z, monoid_mult (monoid_mult x y) z = monoid_mult x (monoid_mult y z)
}.
Record monoidHomo (m n: Monoid) (f: m -> n): Prop :=
{ monoidHomo_zero: f (monoid_zero m) = (monoid_zero n)
; monoidHomo_mult: forall x y, f (monoid_mult m x y) = monoid_mult n (f x) (f y)
}.

(* Specifications: *)
Lemma monoidHomo_refl (m: Monoid): monoidHomo m m (fun x => x).
Definition lift (A: Set) (a: monad A): M A := a >>= (ret ∘ pair (monoid_zero monoid)).