-
-
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
Bring back Applicative.pureEval
or provide equivalent
#1316
Comments
So a good alternative to |
👍 to a |
👍 to |
I'm negative on it being a subclass of Can it possibly take |
Also, I don't see why we want With Next, it seems like this method becomes type equivalent to I am pretty concerned that we have something that on a type level is equivalent to For instance, I made a PR in iteratee that leverages I don't see an issue with the approach there. |
@johnynek the I would also agree to having The The problem right now is that And the problem is that currently there is no type-class that describes Again, just a personal opinion, you folks have way more design experience than I do, but personally I would have preferred: trait Suspendable[F[_]] extends Applicative[F] {
def suspend[A](fa: => F[A]): F[A]
def delay[A](a: => A): F[A] =
suspend(pure(a))
}
trait Memoizable[F[_]] extends Suspendable[F] {
def memoize[A](fa: F[A]): F[A]
def delayOnce[A](a: => A): F[A] =
memoize(delay(a))
} |
Some more thoughts:
|
Can we give some concrete implementations of this type class so we can see I'd like to see examples that are distinct from catchNonFatal on I think abstraction works best when we see several cases it covers. I'd For instance, must delay be lazy? So it is impossible to implement
|
@johnynek It wouldn't be possible to give There's a real difference between contexts with |
But that is only perfectly good if you don't care about the performance
|
#1210 strikes again. It seems we keep trying to work around this. It happened a bit in |
What about something like this: /**
* This is a FunctionK[Eval, F] with the contract that `.value`
* is not called to lift from `Eval` into `F`.
* so a test would be:
*
* var called = false
* val e = Eval.later(called = true)
* val sus: Suspendable[F] = ...
* sus(e)
* called == false
*/
trait SuspendableEval[F[_]] extends FunctionK[Eval, F] {
def apply[T](e: Eval[T]): F[T]
def suspend[T](f: => F[T])(implicit m: FlatMap[F]): F[T] =
m.flatten(apply(Eval.always(f)))
def captureEffect[T](t: => T): F[T] =
apply(Eval.always(t))
} |
actually, with that suspend, who says |
@johnynek I've thought more about this. The question is - who says that I was thinking that we also need to express the ability to "capture effects", otherwise this type-class would be less applicable as we also need to abstract over So forgetting about
Not sure how to express laws for it though. One good law is the one I mentioned, but we can't assume Another law would be the equivalence with |
@alexandru I think it's possible to write laws like that -- we just don't have any right now. But I think it's totally valid to talk about laws that involve two type classes (and maybe we even have some in cats-kernel or algebra). |
Note #2279 pretty much solves this. If you have Defer and Applicative you can implement pureEval. |
Thanks @johnynek |
I see that
pureEval
was removed in this commit and deployed as part of version0.7.0
.The explanation is fine, however it needs to be brought back or it needs an equivalent. There are two reasons for it:
point
pure
can also be used for actual lazy behavior, like when building a lazy generic data-structure; think ofStreaming
(that was moved in Dogs) or checkout this Enumerator type that I've been building. In other words, without a lazypure
, theApplicative
type becomes insufficient for problems such as building a generic lazy list likeCons[F,A](head: A, tail: F[List[A]])
typeThe text was updated successfully, but these errors were encountered: