Skip to content

Attach same mixin multiple times on one carrier  #589

Description

@forrazh

Hello,

On my journey to replace typeclasses by HB in FreeSpec, I stumbled upon an issue with the interfaces.

In FreeSpec, one wants to be able to describe abstract interfaces that can be composed together. For this purpose they introduced a Polymorphic Composite Interface. The main typeclasses used for this are these ones :

Definition interface := Type -> Type.

Class MayProvide (ix i : interface) : Type :=
  { proj_p {α} (e : ix α) : option (i α)
  }.

Class Provide (ix i : interface) `{MayProvide ix i} : Type :=
  { inj_p {α} (e : i α) : ix α
  ; proj_inj_p_equ {α} (e : i α) : proj_p (inj_p e) = Some e
  }.

The best translation I came across in HB is the following one :

Definition interface : UU0 := (UU0 -> UU0).

HB.structure Definition MayProvide (i : interface) :=
    { ix of IsMayProvide i ix }. 

HB.mixin Record IsProvide ( i ix : interface ) of MayProvide i ix := {
  inj_p : forall {α : UU0}, i α -> ix α;
  proj_inj_p_equ :
    forall {α : UU0} (e : i α),
      proj_p α (inj_p e) = Some e
}.

HB.structure Definition Provide (i : interface) :=
    { ix of IsProvide i ix & IsMayProvide i ix }. 

Where ix (the composite interface) becomes the carrier.

But now, I need to design multiple providers. In FreeSpec, we find two examples :

(* Provide multiple *)
Class Provide2 ix i1 i2 `{Provide ix i1, Provide ix i2}.
(* Don't mess up the interfaces *)
Class Distinguish (ix i j : interface) `{Provide ix i, MayProvide ix j} : Prop :=
  { 
    distinguish : forall {α} (e : i α), proj_p (i := j) (inj_p (ix := ix) e) = None
  }.

And I can manage to make something that types for both in HB :

HB.mixin Record IsProvide2 (i j ix : interface) of Provide i ix & Provide j ix := {
}.

HB.structure Definition Provide2 (i j : interface) := 
    {ix of IsProvide2 i j ix 
        & Provide j ix & MayProvide j ix
        & Provide i ix & MayProvide i ix 
     }.

(* A first description before Distinguish *)
HB.mixin Record IsCombinedProvider (i j ix : interface) of Provide i ix & MayProvide j ix & MayProvide i ix:= {
}.
HB.structure Definition CombinedProvider (i j : interface) := 
    {ix of IsCombinedProvider i j ix & IsProvide i ix & IsMayProvide j ix & IsMayProvide i ix }.

But, the problem arises when I want to use the first interface provided (i) for ix :

Example section :

Section t.
    Variables (i j : interface) (ix : Provide2.type i j).
    Variables (α : UU0) (e : i α).
Check inj_p.
(*
inj_p
     : forall α0 : UU0, ?i α0 -> ?s α0
where
?i : [i : interface j : interface ix : Provide2.type i j α : UU0 e : i α |- interface]
?s : [i : interface j : interface ix : Provide2.type i j α : UU0 e : i α
|- Provide.type ?i]
*)
Check inj_p (s:=ix).
(*
inj_p
     : forall α : UU0, j α -> ix α
 *)
Fail Check proj_p (s:=ix) (i:=i).
(*
The command has indeed failed with message:
In environment
i, j : interface
ix : Provide2.type i j
α : UU0
e : i α
The term "ix" has type "Provide2.type i j" while it is expected to have type
"MayProvide.type i".
*)
HB.about Provide2.
(* 
HB: Provide2.type is a structure (from "(stdin)", line 3)
HB: Provide2.type characterizing operations and axioms are:
HB: Provide2 is a factory for the following mixins:
    - IsMayProvide
    - IsProvide
    - IsProvide2 (* new, not from inheritance *)
HB: Provide2 inherits from:
    - MayProvide
    - Provide
HB: Provide2 is inherited by:
*)

HB.about MayProvide.
(* 
HB: MayProvide.type is a structure (from "(stdin)", line 19)
HB: MayProvide.type characterizing operations and axioms are:
    - proj_p
HB: MayProvide is a factory for the following mixins:
    - IsMayProvide (* new, not from inheritance *)
HB: MayProvide inherits from:
HB: MayProvide is inherited by:
    - Provide
    - CombinedProvider
    - Provide2
*)

End t.

Hence my questions :

  • Is it that is not handled (yet?) ?
  • Is the idea of having one carrier supporting multiple instances of a type against the HB philosophy ?
  • Is it just something that I try to do wrongly ?

If I can help on any development or providing more information, just tell me !

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions