-
Notifications
You must be signed in to change notification settings - Fork 53
Shortcomings of subevents #130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The common issue with One solution may be to replace (or wrap) Definition sum_of : list (Type -> Type) -> Type -> Type. |
Here's a PoC to try and address the second point. The idea is to define a type class indexed by instances of Require Import ITree.ITree.
Require Import ITree.ITreeFacts.
(* A class of event transformations. *)
Class Swap (E : Type -> Type) : Type := swap : E ~> E.
Instance Swap_left E F `(Swap E) : Swap (E +' F) := fun _ e =>
match e with
| inl1 e => inl1 (swap _ e)
| inr1 f => inr1 f
end.
Instance Swap_right E F `(Swap F) : Swap (E +' F) := fun _ e =>
match e with
| inl1 e => inl1 e
| inr1 f => inr1 (swap _ f)
end.
(* A swappable event type *)
Variant fooE : Type -> Type :=
| Foo : bool -> fooE nat
.
Instance Swap_foo : Swap fooE := fun _ e =>
match e with
| Foo b => Foo (negb b)
end.
(* A predicate class of [subevent] ([-<]) instance which behave well
with respect to [Swap] *)
Class SwapGood (E F : Type -> Type) `(E -< F) `(Swap E) `(Swap F) : Prop :=
swap_good : forall X (e : E X),
swap _ (subevent _ e)
= @subevent E F _ _ (swap _ e).
Instance SwapGoodLeft (E F G : Type -> Type) `(SwapGood E F)
: SwapGood E (F +' G) _ _ _ := {}.
Proof.
intros. cbv in *. congruence.
Qed.
Instance SwapGoodRight (E F G : Type -> Type) `(SwapGood E G)
: SwapGood E (F +' G) _ _ _ := {}.
Proof.
intros. cbv in *. congruence.
Qed.
Lemma test {E F X} `{Swap E} `{Swap F} `{E -< F} (SG : SwapGood E F _ _ _) (e : E X) :
swap _ (@subevent E F _ _ e)
= @subevent E F _ _ (swap _ e).
Proof.
rewrite swap_good.
reflexivity.
Qed. |
That is indeed a light-weight way to proceed that seems reasonable in this particular case, thanks for the suggestion. Despite the quite specific name I was trying to think if this approach can be straightforwardly extended to effect morphisms in general rather than just homomorphisms, but it falls short since we need to somehow express the type resulting from the substitution of the subeffect |
From our discussion just now I finally understand that by "homomorphism" you mean "endomorphism"
|
Oh sorry for the brain fart, I indeed meant endomorphism! And right that would give something like that:
That actually looks alright, I'll try toying with it asap! |
As has been discussed several times, the current support for subevents seems insufficient for practical use. This issue details a couple of concrete difficulties it raised as we used them in the Vellvm project, and suggests a potential line of action. The proposed solution is quite vague and meant as a start for discussions.
-------------------------- First concrete issue --------------------------
The first difficulty is in the definition of handlers in a fairly large ambient context of events.
Consider we want to interpret into the state monad a set of events
LocalE
. We hence have a handler:Definition handle_Local {E} : (LocalE k v) ~> stateT map (itree E) := ...
Now we would like to run the corresponding interpreter. However, currently, the definition of this interpreter has to be tailored extremely closely to the structure of the ambiant universe of events. More concretely, events being associated to the right, we are currently working in a context of the form
F +' G +' LocalE +' H
for some concrete values ofF, G, H
.We hence need the following definition:
Not only is this definition naturally unsatisfactory, but it breaks if we add or remove a family of events in the wrong place during a refactoring, and cannot be used in another context, something that turns out to be useful.
It hence seems that a first "feature request` would be to have a systematic way to extend handlers to subsets of events.
-------------------------- Second concrete issue --------------------------
Now the second difficulty, which very much relates to the first, appears when we start proving transformations on the trees. Consider a typeclass
Swap A := {| swap: A -> A |}
of types equipped with an endomorphism swapping the names of two identifiers fixed at the top level.The instance for
LocalE
is non-trivial, since its events take identifiers as arguments. On other domains of events, it is the identity. We can of course define an instance for+'
.On itrees, to swap is defined as
swap t := map swap (translate swap t)
.Now one thing that we need to prove is that
swap
commute with the triggering of the subevents we use in the semantics. That is ideally thatswap (@trigger E X (subevent e)) \cong @trigger E X (subevent (swap e))
, assumingSwap E
and some things aboutX
.However this cannot be proved, since
F -< E
gives us an embedding fromF
intoE
, but tells us nothing about this image ofF
inE
.In order to prove such a lemma, we actually need to fix not only
F
, but alsoE
. Worse, the proof relies actively on the specific instance forF -< E
that gets inferred, that is essentially relies on the fact thatReSum_inl
andReSum_inr
can be inversed.This leads to a significant amount of ad-hoc lemmas with duplicated proofs.
-------------------------- Feature request? --------------------------
To sum up, currently, the
-<
typeclass does not expose enough information to define generic constructs and prove generic lemmas about them. We would in particular like to be able: givenh:E ~> M
andE -< F
, deriveF ~> M
that should intuitively behave as h over the embedding ofE
intoF
, and as some kind of identity otherwise.This seems to suggest notably that an instance
E -< F
should not only provide an embeddingE -> F
, but also a membership testis_in_E: F -> bool
Since the handler goes into a monad in general, it is not exactly an identity that we need. Looking back at our first issue, we need the monad to support some generalized way of triggering the event into the monad.
This would be a typeclass
Events E M := {trigger: E ~> M}
that has the obvious instance foritree E
, as well as instances for the monad transformers we support, typically a{Events E M} -> {Events E (stateT _ M}}
.Finally we naturally need the instances to come with reasonnable reasoning principle to adress the second issue described above.
Best,
Yannick
The text was updated successfully, but these errors were encountered: