lexi-lambda / freer-simple

A friendly effect system for Haskell
https://hackage.haskell.org/package/freer-simple
BSD 3-Clause "New" or "Revised" License
227 stars 19 forks source link

Too fast too free #24

Closed isovector closed 5 years ago

isovector commented 5 years ago

This PR is the first step towards sweet perf gains in freer-simple. I've left some commentary inline in the review on particularly prickly points that deserve discussion.

isovector commented 5 years ago

One idea I'm toying strongly with is to release the core Eff monad and interpretations in its own package, and then change this PR to add a dependency and implement your combinators in terms of those.

The pros:

This seems roughly analogous with the streaming library situation; they're all a little different in terms of guiding principles, but interop is just a function call away.

Thoughts?

lexi-lambda commented 5 years ago

Sorry for taking so long to get to this. I’ve had some things going on, but I’m hoping I’ll be able to be significantly more responsive going forward.

One idea I'm toying strongly with is to release the core Eff monad and interpretations in its own package, and then change this PR to add a dependency and implement your combinators in terms of those.

I have mixed feelings about this. In some respect, you’re probably right that there are some nontrivial merits to what you’re describing. On the other hand, I wish we could work through the social problem and agree to standardize around something in the effects space, and your proposal specifically makes it easier to not do that. I know that in this case, it doesn’t seem like a big deal, and maybe it even seems advantageous—we solve the technical problem of lack of interoperation between different parts of the effect ecosystem—but I worry about the social fragmentation it might lead to by discouraging the development of a shared vocabulary for these concepts.

It would be one thing if we had two competing ecosystems, both of which have seen large adoption, like pipes and conduit. In a case like that, I’d say: absolutely, if it’s possible to extract a shared core implementation that allows interoperation between those two ecosystems, that’d be a huge win. But we don’t really have that in the extensible effects world, and this seems too premature to me. I don’t get the sense we’d see any existing effects packages switching to the shared backend, so it’d just fragment the ecosystem further with even more frontend APIs.

Plus, the flexibility of the package being self-contained is nice. It means making backwards-incompatible changes, even to the core, doesn’t involve a very complicated process of synchronizing version numbers across projects and ensuring that everything stays buildable in all configurations. Instead, we can just make the change, bump one of the major version numbers, and cut a release. I think that’s a win.

isovector commented 5 years ago

Fair enough! I've spent the last few weeks thinking long and hard about effect systems. Since then I've come around to viewing your Control.Monad.Freer combinators as better fundamental choices than the freer-effects ones. Yours offer better composition and adequately solve my "I wish these things would compose better" complaint.

isovector commented 5 years ago

Some additional thoughts:

At the same time, I've been working my way through the (far too complicated) internals of fused-effects. I like that they're capable of providing second-order effects, but the conceptual cost of implementation is staggeringly high.

It seems to me like we could lift second-order effects into freer-simple to give advanced-users the technology, but focus most of the technology on first-order effects. The Lift combinator from fused-effects does this transformation from first-to-second order.

~That being said, their bracket implementation is still pretty wonky, which to me is the primary use-case. Their bracket will successfully trap short-circuiting effects, but incorrectly thread state. There are probably bespoke solutions for individual use-cases, but I'm not convinced the effect is doable in general (short of some new primitives to explicit set the IO masking state).~

isovector commented 5 years ago

All of this is to say---how willing are you to introduce higher-order effects to freer-simple if we can do it without affecting the conceptual complexity for first-order users? ~How willing are you, even if it means we still can't write a satisfactory bracket?~

lexi-lambda commented 5 years ago

Since then I've come around to viewing your Control.Monad.Freer combinators as better fundamental choices than the freer-effects ones. Yours offer better composition and adequately solve my "I wish these things would compose better" complaint.

Hooray! :)

At the same time, I've been working my way through the (far too complicated) internals of fused-effects. I like that they're capable of providing second-order effects, but the conceptual cost of implementation is staggeringly high.

This has largely been my impression, too, though I haven’t taken the time to examine fused-effects very closely, so I don’t really understand all the details. It seems really neat, but it does seem to prioritize screaming fast performance over interface simplicity… which is quite the opposite goal of this package!

That said, while I haven’t ever had the opportunity to use higher-order effects, and certainly not in anger, they seem like a strict improvement with no inherent downsides. If you could devise a way to make them work without making freer-simple’s existing API more complicated, that’d be awesome. It seems like, even if that doesn’t let us have bracket, it’d still be a net win, no?

isovector commented 5 years ago

Just kidding---bracket in fused-effects works fine, I was just doing it wrong.

I'm reasonably sure I can get the freer-simple API working with the performance and capabilities of fused-effects. Let's hold off on this PR until I have something to back up that claim :)

lexi-lambda commented 5 years ago

Okay—that sounds exciting! Should I hold my breath? :)