Library FreeSpec.FFI.Refs


Set Implicit Arguments.
Unset Strict Implicit.
Set Contextual Implicit.
Generalizable All Variables.

From CoqFFI Require Export Extraction.
From SimpleIO Require Import IO_Monad.
From CoqFFI Require Import Interface.

Types


Axiom (reference : ∀ (a : Type), Type).

Extract Constant reference "'a" ⇒ "'a FreeSpecFFI.Refs.reference".

Impure Primitives

Monad


Class MonadRefs (m : Type → Type) : Type :=
  { make_ref : ∀ (a : Type), a → m (reference a)
  ; deref : ∀ (a : Type), reference a → m a
  ; assign : ∀ (a : Type), reference a → a → m unit
  }.

IO Instance


Axiom (io_make_ref : ∀ (a : Type), a → IO (reference a)).
Axiom (io_deref : ∀ (a : Type), reference a → IO a).
Axiom (io_assign : ∀ (a : Type), reference a → a → IO unit).

Extract Constant io_make_ref ⇒
  "(fun x0 k__ -> k__ (FreeSpecFFI.Refs.make_ref x0))".
Extract Constant io_deref ⇒
  "(fun x0 k__ -> k__ (FreeSpecFFI.Refs.deref x0))".
Extract Constant io_assign ⇒
  "(fun x0 x1 k__ -> k__ (FreeSpecFFI.Refs.assign x0 x1))".

Instance MonadRefs_IO : MonadRefs IO :=
  { make_ref := io_make_ref
  ; deref := io_deref
  ; assign := io_assign
  }.

Interface Definition


Inductive REFS : Type → Type :=
| Make_ref : ∀ (a : Type), a → REFS (reference a)
| Deref : ∀ (a : Type), reference a → REFS a
| Assign : ∀ (a : Type), reference a → a → REFS unit.

Definition inj_make_ref `{Inject REFS m} (a : Type) (x0 : a)
  : m (reference a) :=
  inject (Make_ref x0).

Definition inj_deref `{Inject REFS m} (a : Type) (x0 : reference a) : m a :=
  inject (Deref x0).

Definition inj_assign `{Inject REFS m} (a : Type) (x0 : reference a) (x1 : a)
  : m unit :=
  inject (Assign x0 x1).

Instance MonadRefs_Inject `(Inject REFS m) : MonadRefs m :=
  { make_ref := inj_make_ref
  ; deref := inj_deref
  ; assign := inj_assign
  }.