You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Now that language-ext has Functor and Applicative traits, there are a number of extension methods[1][2] and module functions[3][4] that work with those traits.
Those all return the abstract K<F, A> type rather than the more specialised types that derive from K<F, A>. So, to get over that, I had previously added bespoke extensions for types like Either, Option, etc. that would call the generic behaviours and then cast back to the specialised type.
Unfortunately, over the years there's been an inconsistent application of these extension methods to the various functor/applicative types. So, I have now made all functors/applicatives support the exact same set of Map, Apply, Action extensions as well as the exact same set of map, apply, action functions in the Prelude.
That means for some types you may have lost some extensions/functions and for some they have gained. But, they are now all consistent, so going forward at least there's no second guessing.
One big change is that the multiple operand Apply has gone, so you can't do this now:
You must fluently chain calls to Apply (which is just what it did behind the scenes anyway):
varmr= mf.Apply(mx).Apply(my);
The variants of Map and Apply that took multi-argument Func delegates as their first argument are now all only available as generic extensions and only accept a single operand, e.g:
publicstaticK<AF,Func<B,Func<C,D>>>Apply<AF,A,B,C,D>(thisK<AF,Func<A,B,C,D>>mf,K<AF,A>ma)whereAF:Applicative<AF>=>
AF.Apply(AF.Map(curry, mf), ma);publicstaticK<AF,Func<B,Func<C,Func<D,E>>>>Apply<AF,A,B,C,D,E>(thisK<AF,Func<A,B,C,D,E>>mf,K<AF,A>ma)whereAF:Applicative<AF>=>
AF.Apply(AF.Map(curry, mf), ma);// ... etc. up to 10 parameter Func delegates
Note, how the multi-parameter Func delegates turn into single parameter curried Func results.
What that means is each bespoke extension method (say, for Option, like below) just needs to handle Func<A, B> and not all variants of n-argument function. All chained Apply calls will eventually bake down to a concrete type being returned, removing the need to call .As() afterwards.
The Prelude now has map, apply, and action functions for all applicatives. I think it's worth pointing out that map is particularly useful in making the use of applicatives a bit easier. Previously, if you needed to lift up an anonymous lambda, you'd need to call fun(x => ...) to make the delegate available:
varmr= fun((intx,inty)=>x+y).Map(mx).Apply(my);
Now, with the map overrides, you can avoid the initial lifting of the function and perform the lift and map all in one:
varmr= map((intx,inty)=>x+y, mx).Apply(my);
Of course, the tuple-based approach is also available for all applicatives:
varmr=(mx, my).Apply((x,y)=>x+y);
This however returns the generic K<F, A> and needs .As() to make it concrete.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Now that language-ext has
Functor
andApplicative
traits, there are a number of extension methods[1][2] and module functions[3][4] that work with those traits.Those all return the abstract
K<F, A>
type rather than the more specialised types that derive fromK<F, A>
. So, to get over that, I had previously added bespoke extensions for types likeEither
,Option
, etc. that would call the generic behaviours and then cast back to the specialised type.Unfortunately, over the years there's been an inconsistent application of these extension methods to the various functor/applicative types. So, I have now made all functors/applicatives support the exact same set of
Map
,Apply
,Action
extensions as well as the exact same set ofmap
,apply
,action
functions in thePrelude
.That means for some types you may have lost some extensions/functions and for some they have gained. But, they are now all consistent, so going forward at least there's no second guessing.
One big change is that the multiple operand
Apply
has gone, so you can't do this now:You must fluently chain calls to
Apply
(which is just what it did behind the scenes anyway):The variants of
Map
andApply
that took multi-argumentFunc
delegates as their first argument are now all only available as generic extensions and only accept a single operand, e.g:Note, how the multi-parameter
Func
delegates turn into single parameter curriedFunc
results.What that means is each bespoke extension method (say, for
Option
, like below) just needs to handleFunc<A, B>
and not all variants of n-argument function. All chainedApply
calls will eventually bake down to a concrete type being returned, removing the need to call.As()
afterwards.The
Prelude
now hasmap
,apply
, andaction
functions for all applicatives. I think it's worth pointing out thatmap
is particularly useful in making the use of applicatives a bit easier. Previously, if you needed to lift up an anonymous lambda, you'd need to callfun(x => ...)
to make the delegate available:Now, with the
map
overrides, you can avoid the initial lifting of the function and perform the lift and map all in one:Of course, the tuple-based approach is also available for all applicatives:
This however returns the generic
K<F, A>
and needs.As()
to make it concrete.This discussion was created from the release Map and Apply standardisation.
Beta Was this translation helpful? Give feedback.
All reactions