Make StackSafeMonad extend Defer - #3962
Conversation
djspiewak
left a comment
There was a problem hiding this comment.
I like where this is going. I had a similar thought around the Lazy[_] idea but still trying to piece through how we can make it not-horrible.
| def shiftFunctor[F[_], A, B](fn: A => F[B])(implicit F: Functor[F]): A => F[B] = | ||
| F match { | ||
| case ssm: StackSafeMonad[F] @unchecked => { a => ssm.defer(fn(a)) } | ||
| case _ => fn | ||
| } |
There was a problem hiding this comment.
I wonder if there's a way to make this more general. A => F[B] works extremely well for Kleisli and extremely not-well for almost anything else, since it will force boxing into a Function1 in cases where it just isn't needed.
There was a problem hiding this comment.
Maybe it shouldn't be public at all. I just took what was in Kleisli and made it more particular. I think the current Kleisli hack is adding cost for any Monad that isn't lazy (e.g. Option, or Either), and this function will help there.
There was a problem hiding this comment.
When in doubt, leave it private. Can always publicize it later if someone finds a second use.
Accept @djspiewak's suggestions Co-authored-by: Daniel Spiewak <djspiewak@gmail.com>
|
@djspiewak please take a look and see what you think with your changes merged. |
Make StackSafeMonad extend Defer.
See the discussion in #3790 for more context.
The argument for why this is safe is given in the comments on StackSafeMonad. If they don't seem to make sense, please add a comment there.
cc @djspiewak @non
I think we can follow up with using an idea similar to
shiftfrom Kleisli to make an Applicative map2 abstraction. As a sketch:and then we can either make
Lazy[A] = Eval[A]orLazy[A] = Id[A]depending on theF[_]which maybe we can reflectively select based on if theF[_]is aStackSafeMonador not.Or something...