Skip to content
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

Open to including a "ControlTransformation" data type? #63

Open
shlevy opened this issue Dec 16, 2022 · 8 comments
Open

Open to including a "ControlTransformation" data type? #63

shlevy opened this issue Dec 16, 2022 · 8 comments

Comments

@shlevy
Copy link

shlevy commented Dec 16, 2022

As MonadTrans relates to a natural transformation, MonadTransControl roughly relates to a type like this:

data ControlTransformation st m n = ControlTransformation
  { transWith :: !(forall a. ((forall x. n x -> m (st x)) -> m a) -> n a)
  , restoreState :: !(forall a. st a -> n a)
  }

type StatelessControlTransformation = ControlTransformation Identity

statelessControlTransformation
  :: forall m n. (Functor m, Applicative n)
  => (forall a. ((forall x. n x -> m x) -> m a) -> n a)
  -> StatelessControlTransformation m n

statelessTransWith
  :: (Functor m)
  => StatelessControlTransformation m n
  -> ((forall x. n x -> m x) -> m a) -> n a

Would this type belong somewhere in monad-control?

@phadej
Copy link
Collaborator

phadej commented Dec 16, 2022

What is ControlTransformation useful for?

@shlevy
Copy link
Author

shlevy commented Dec 16, 2022

The application I want to use it for is a better solution to what I called "the instrumented capability problem" in the docs at https://hackage.haskell.org/package/eventuo11y-0.5.0.0/docs/Observe-Event-BackendModification.html.

Basically, if you're managing effects like:

data FooEffects m = FooEffects
  { countBars :: BarPath -> m Int
  , checkpointFoo :: m ()
  }

you'll often have a function like

hoistFoo :: (forall x. m x -> n x) -> FooEffects m -> FooEffects n

But this can't be written if one of your effects has m in negative position, i.e. the same cases where we want MonadBaseControl/MonadUnlift* in mtl style.

Instead of a natural transformation, though, you can hoist an effect record like this along a ControlTransformation

@phadej
Copy link
Collaborator

phadej commented Dec 16, 2022

I see. Except we cannot convert StM to st, because StM takes a. There's an issue #39 for doing this, and I tried to implement it in #55, but it just isn't nice if Monad m (or Functor) doesn't imply forall x y. Coercible x y => Coercible (m x) (m y). (TL;DR dealing with Identity makes things quite inconvenient to use).

@shlevy
Copy link
Author

shlevy commented Dec 16, 2022

Right, I ran into that too. I think this might be solvable if we could take a parameter role as a constraint (Not sure how this would be spelt, a prettier/more general version of FirstParamIsRepresentational m) and then the coercion would be generated.

If this were fixed, would that impact your interest in adding this? Even though we can't straightforwardly do the conversion currently, it's still morally a concept pertaining to "monad control" in the same way the typeclasses here do.

@shlevy
Copy link
Author

shlevy commented Dec 16, 2022

Via @amesgen, one option might be to simply have forall x y. Coercible x y => Coercible (m x) (m y) as a constraint on your declaration... Not sure if that solves the problem, haven't looked into the details of your PR

@shlevy
Copy link
Author

shlevy commented Dec 16, 2022

@shlevy
Copy link
Author

shlevy commented Dec 16, 2022

Well I'm embarrassed that I recommended you your own post... 😅

@shlevy
Copy link
Author

shlevy commented Dec 17, 2022

@phadej Yep, it works without fmapCoerce now #64

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants