Library flat

Require Import Setoid.
Require Import List.
Require Import NArith.

Require Import basics.
Require Import preord.
Require Import categories.
Require Import sets.
Require Import finsets.
Require Import esets.
Require Import effective.
Require Import directed.
Require Import plotkin.
Require Import joinable.
Require Import approx_rels.
Require Import cpo.
Require Import profinite.

Flat pointed domains

Every enumerable type can be turned into a flat profinite domain. These are useful for representing base types.

Module enumtype.
  Record enumtype :=
  { carrier :> Type
  ; enumtype_set : N -> option carrier
  ; enumtype_complete : forall x, exists n, enumtype_set n = Some x
  ; enumtype_dec : forall x y:carrier, {x=y}+{x<>y}

  Definition eq_mixin (X:enumtype) : Eq.mixin_of (carrier X) :=
    Eq.Mixin (carrier X) (@eq _)
    (@Logic.refl_equal _) (@Logic.eq_sym _) (@Logic.eq_trans _).

  Definition preord_mixin (X:enumtype) : Preord.mixin_of (carrier X) :=
    Preord.Mixin (carrier X) (@eq _) (@Logic.refl_equal _) (@Logic.eq_trans _).

  Canonical Structure setoid (X:enumtype) : Eq.type :=
    Eq.Pack X (eq_mixin X).
  Canonical Structure ord (X:enumtype) : preord :=
    Preord.Pack X (preord_mixin X).

  Lemma order_discrete (X:enumtype) (x y:X) : x y -> x = y.

  Lemma strong_eq (X:enumtype) (x y:X) : x y -> x = y.

  Program Definition enumtype_effective X : effective_order (ord X) :=
    EffectiveOrder (ord X) (enumtype_dec X) (enumtype_set X) _.

  Lemma enumtype_has_normals (X:enumtype) :
    has_normals (ord X) (enumtype_effective X) true.

  Definition enumtype_plotkin (X:enumtype) : plotkin_order true (ord X) :=
    norm_plt (ord X) (enumtype_effective X) true (@enumtype_has_normals X).
End enumtype.

Notation enumtype := enumtype.enumtype.
Notation Enumtype := enumtype.Enumtype.

Canonical Structure enumtype.setoid.
Canonical Structure enumtype.ord.
Coercion enumtype.carrier : enumtype >-> Sortclass.

Canonical Structure flat (X:enumtype) : PLT :=
    PLT.Ob true (enumtype.carrier X)
      (PLT.Class _ _
        (enumtype.preord_mixin X)
        (enumtype.enumtype_effective X)
        (enumtype.enumtype_plotkin X)).

Program Definition flat_elem (Y:enumtype) (y:Y) : PLT.unit true flat Y :=
  PLT.Hom true (PLT.unit true) (flat Y) (single (tt,y)) _ _.

Lemma flat_elem_inj Y : forall y1 y2,
  flat_elem Y y1 flat_elem Y y2 -> y1 = y2.

Section flat_cases.
  Variable X:enumtype.
  Variables (A B:PLT).
  Variable f : X -> (A B).

  Program Definition insert_index (x:X) : Preord.hom (A×B)%cat_ob ((A×flat XB)%cat_ob :=
    Preord.Hom (A×B)%cat_ob ((A×flat XB)%cat_ob (fun ab => ((fst ab, x), snd ab)) _.

  Program Definition map_indexes : Preord.hom (flat X) (eset ((PLT.ord A×flat XPLT.ord B)%cat_ob) :=
    Preord.Hom (flat X) (eset ((A× flat XB)%cat_ob)
      (fun x => image (insert_index x) (PLT.hom_rel (f x))) _.

  Definition flat_cases_rel : erel (PLT.ord A×flat X)%cat_ob (PLT.ord B) :=
    union (image map_indexes (enumtype.enumtype_set X : eset (flat X))).

  Lemma flat_cases_rel_elem : forall x a b,
    ((a,b) PLT.hom_rel (f x) <-> (a,x,b) flat_cases_rel).

  Program Definition flat_cases : A flat X B :=
    PLT.Hom true ( A (flat X)) B flat_cases_rel _ _.

  Lemma flat_cases_elem C x h :
    flat_cases h, flat_elem x PLT.terminate true C f x h.
End flat_cases.

Lemma flat_cases_univ (X:enumtype) (A B:PLT) (f:X -> A B) q :
  (forall x, f x q id, flat_elem x PLT.terminate _ _) ->
  flat_cases f q.

Lemma flat_cases_commute : forall (X : enumtype) (A B C : PLT)
  (f : X -> A B) (g:C A) (h:C flat X),
  flat_cases f g, h flat_cases (fun x => f x g) id, h .

Definition boolset : N -> option bool :=
  fun n => match n with N0 => Some true | _ => Some false end.

Program Definition enumbool : enumtype :=
  Enumtype bool boolset _ _.

Canonical Structure enumbool.