-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Introduce Apply.TraverseStrategy #3993
Conversation
It would be nice to benchmark this approach for Since I guess almost all instances will be direct or viaEval, I would hope the JIT won't see a megamorphic call site and will pretty much inline this as though it had been written by hand. |
I'll add some more thoughts shortly, but very quickly… this is indeed going to be megamorphic. All of the call sites on Is there any way we can exploit the fact that there are really only two modalities here, lazy and eager? When I was first thinking about this problem space, I actually assumed we would simply write two different implementations of |
I should have been more clear: I think it won't be megamorphic because I assume most apps will only be using Direct or ViaEval, but that may be incorrect. Also, I guess almost all of our typeclasses are megamorphic, so I don't think this would be a perf hit anyway, but it would be good to see some benchmarks I think. I think the problem is there really aren't two ways to do this. Take Kleisli for instance, we actually have a note in the code that it's So, I think ideally we wouldn't have map2Eval at all, and we would just have this TraverseStrategy and let each type define its |
@djspiewak I'm going to close this since I actually am not that concerned about the performance, but I think this approach is sound and is a good mechanism to allow types to communicate how their traverse should work. Feel free to steal any of this code or ideas in any follow up. It would be nice for traverse on IO to be faster I guess, but that's your department. ;) |
Relaying some notes from discord:
and
|
This introduces an extension to Apply designed to make traverse and traverse-like functions faster.
The idea is to have a small set of function, sufficient to implement traverse, that work together to handle the laziness of the type constructor.
This allows strict types such as
Either[E, *]
orTry
orList
which can have useful short-circuiting behavior, to allow the Traverse instance to use that via Eval, but types suchEval
,IO
,Validated[E, *]
,NonEmptyList
, etc.. that don't need that laziness, they can directly usemap2
without the wasteful boxing.related to #3790 and #3962
interested in your comments @djspiewak @non