Record mixin_of (T : Type) := Mixin {
  ounit_op : T;
  ojoin_op : T -> T -> option T;
  ojoinC_op : forall x y, ojoin_op x y = ojoin_op y x;
  ojoinA_op : forall x y z, 
    obind (ojoin_op x) (ojoin_op y z) = obind (ojoin_op^~ z) (ojoin_op x y);
  ounitL_op : forall x, ojoin_op ounit_op x = Some x}.Record mixin_of (T : Type) := Mixin {
  ounit_op : T;
  ojoin_op : T -> T -> option T;
  ojoinC_op : forall x y, ojoin_op x y = ojoin_op y x;
  ojoinA_op : forall x y z, 
    obind (ojoin_op x) (ojoin_op y z) = obind (ojoin_op^~ z) (ojoin_op x y);
  ounitL_op : forall x, ojoin_op ounit_op x = Some x}.Record mixin_of (T : Type) := Mixin {
  ounit_op : T;
  ojoin_op : T -> T -> option T;
  ojoinC_op : forall x y, ojoin_op x y = ojoin_op y x;
  ojoinA_op : forall x y z, 
    obind (ojoin_op x) (ojoin_op y z) = obind (ojoin_op^~ z) (ojoin_op x y);
  ounitL_op : forall x, ojoin_op ounit_op x = Some x}.Record mixin_of (T : Type) := Mixin {
  ounit_op : T;
  ojoin_op : T -> T -> option T;
  ojoinC_op : forall x y, ojoin_op x y = ojoin_op y x;
  ojoinA_op : forall x y z, 
    obind (ojoin_op x) (ojoin_op y z) = obind (ojoin_op^~ z) (ojoin_op x y);
  ounitL_op : forall x, ojoin_op ounit_op x = Some x}.Record mixin_of (T : Type) := Mixin {
  ounit_op : T;
  ojoin_op : T -> T -> option T;
  ojoinC_op : forall x y, ojoin_op x y = ojoin_op y x;
  ojoinA_op : forall x y z, 
    obind (ojoin_op x) (ojoin_op y z) = obind (ojoin_op^~ z) (ojoin_op x y);
  ounitL_op : forall x, ojoin_op ounit_op x = Some x}.Record mixin_of (T : Type) := Mixin {
  ounit_op : T;
  ojoin_op : T -> T -> option T;
  ojoinC_op : forall x y, ojoin_op x y = ojoin_op y x;
  ojoinA_op : forall x y z, 
    obind (ojoin_op x) (ojoin_op y z) = obind (ojoin_op^~ z) (ojoin_op x y);
  ounitL_op : forall x, ojoin_op ounit_op x = Some x}.Record mixin_of (T : Type) := Mixin {
  ounit_op : T;
  ojoin_op : T -> T -> option T;
  ojoinC_op : forall x y, ojoin_op x y = ojoin_op y x;
  ojoinA_op : forall x y z, 
    obind (ojoin_op x) (ojoin_op y z) = obind (ojoin_op^~ z) (ojoin_op x y);
  ounitL_op : forall x, ojoin_op ounit_op x = Some x}.Notation class_of := mixin_of (only parsing).Structure type : Type := Pack {sort : Type; _ : class_of sort}.Structure type : Type := Pack {sort : Type; _ : class_of sort}.Structure type : Type := Pack {sort : Type; _ : class_of sort}.Definition class := let: Pack _ c as cT' := cT return class_of cT' in c.Definition pack c := @Pack T c.Definition clone := fun c & cT -> T & phant_id (pack c) cT => pack c.Definition ounit := ounit_op class.Definition ojoin := ojoin_op class.Notation unlifted := type.Notation UnliftedMixin := Mixin.Notation Unlifted T m := (@pack T m).Notation "[ 'unliftedMixin' 'of' T ]" := (class _ : mixin_of T)
  (at level 0, format "[ 'unliftedMixin'  'of'  T ]") : form_scope.Notation "[ 'unlifted' 'of' T 'for' C ]" := (@clone T C _ idfun id)
  (at level 0, format "[ 'unlifted'  'of'  T  'for'  C ]") : form_scope.Notation "[ 'unlifted' 'of' T ]" := (@clone T _ _ id id)
  (at level 0, format "[ 'unlifted'  'of'  T ]") : form_scope.Notation ounit := ounit.Notation ojoin := ojoin.

Lemma ojoinA (U : unlifted) (x y z : U) : obind (ojoin x) (ojoin y z) = obind (@ojoin U^~ z) (ojoin x y).