-
Notifications
You must be signed in to change notification settings - Fork 71
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
Interop with MTL classes #36
Comments
Some points:
Point 3 seems like the best to me, especially because you can implement it separately from the effect, and it has no relation on the effect's algebra. For example, you could write: liftRandomIO
:: (Member RandomFu r, Member (Lift IO) r)
=> (forall m. MonadRandom m => m a)
-> Sem r a by just instantiating your forall'd However, working backwards like this I think is the wrong strategy. If you have in mind "I want to use We learned this lesson the hard way at Takt, where we wanted a
|
TL;DR: yes.
I agree about building up effects in this way, one which defers and makes flexible all the decisions about implementation by limiting your power to just what you need. And that's sort of the idea of the mtl constraints, right? So we agree, I think. We don't want to encourage using specific implementations. [Sidebar 1: That talk is cool! Though I'll need to watch the adjunctions part again. And, maybe I missed it, but when talking about Applicative vs. Monad, I wished he mentioned parallelism. To me, that's one of the coolest examples and clearest examples of why using more general things gets you more power. I mean, also lenses, but ouch.] And thus the question/idea: Can we write the function I proposed in #3, but without sendM? Can we discharge the constraint by, at the most extreme, creating a dictionary on the fly which routes the calls through the Random or RandomFu effect? Then I think we're accomplishing both of our goals: we encourage and support writing against higher abstractions (either Is what you meant by "packaging it with the effect" something like newtype RandomSem r a = RandomSem { liftMonadRandom :: P.Sem r a } deriving (Functor, Applicative, Monad)
$(R.monadRandom [d|
instance P.Member Random r => R.MonadRandom (RandomSem r) where
getRandomPrim :: R.Prim t -> RandomSem r t
getRandomPrim = RandomSem . getRandomPrim
|]) ? [Sidebar 2: Having this conversation around the Random effect(s) is confusing it some, because, as you've already pointed out, there shouldn't be two of them! Or, more generally, not all effects will have one-interface-to-rule-them-all and that presents a puzzle at the level of the abstraction rather than the interpretation.] |
Thanks for writing that all out --- I think I understand your point now! The point is: if people have already done their due diligence and written their apps in an MTL-esque tagless final style using At the wildest, we could use But maybe you're right. Maybe the solution is to just embrace orphans, but possibly with the caveat that they must be in their own package and "buyer beware?" It's not a solution for classes with fundeps, but fundamentally I think there's only so much we can do. |
This is fixed by polysemy-research/polysemy-zoo#8, when it lands |
@adamConnerSax on #34 wrote:
A question, slightly off-topic maybe.
I feel like there is something similar about this hoist function and the
MonadRandom
thing we have been talking about over inpolysemy-zoo
.All of them are ways of trying to accommodate a different version of an effect that
polysemy
supports.So, two questions:
polysemy-mtl
orpolysemy-interop
? That would get rid of the dependencies for users who don't care aboutmtl
.hoistX:: Sem (X ': r) a -> XT (Sem r) a
instance (Member X r) => MonadX (Sem r) where ...
liftX :: (MonadX m, Member X r) => m a -> Sem r a
.I'm not quite sure how that third version would work, but it seems like it keeps most of the convenience of instances without the issue of actually having them.
I'm going to think about how to do that for
MonadRandom
inRandomFu
.The text was updated successfully, but these errors were encountered: