-
-
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
Add scala.util.control.TailCalls.TailRec instances #3041
Changes from 5 commits
40c7848
eb1271f
3f0177c
bc144d9
71ac6a4
cc304ca
24f308e
e24a602
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -378,6 +378,7 @@ sealed abstract private[cats] class EvalInstances extends EvalInstances0 { | |
def flatMap[A, B](fa: Eval[A])(f: A => Eval[B]): Eval[B] = fa.flatMap(f) | ||
def extract[A](la: Eval[A]): A = la.value | ||
def coflatMap[A, B](fa: Eval[A])(f: Eval[A] => B): Eval[B] = Later(f(fa)) | ||
override def unit: Eval[Unit] = Eval.Unit | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is unrelated? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes. I added a comment, I just noticed it was missing while looking at Eval. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unrelated, but I noticed we could add this and avoid allocations for some folks that use |
||
} | ||
|
||
implicit val catsDeferForEval: Defer[Eval] = | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package cats | ||
package instances | ||
|
||
import scala.util.control.TailCalls.{done, tailcall, TailRec} | ||
|
||
trait TailRecInstances { | ||
implicit val catsInstancesForTailRec: StackSafeMonad[TailRec] with Defer[TailRec] = | ||
new StackSafeMonad[TailRec] with Defer[TailRec] { | ||
def defer[A](fa: => TailRec[A]): TailRec[A] = tailcall(fa) | ||
|
||
def pure[A](a: A): TailRec[A] = done(a) | ||
|
||
override def map[A, B](fa: TailRec[A])(f: A => B): TailRec[B] = | ||
fa.map(f) | ||
|
||
def flatMap[A, B](fa: TailRec[A])(f: A => TailRec[B]): TailRec[B] = | ||
fa.flatMap(f) | ||
|
||
override val unit: TailRec[Unit] = done(()) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package cats | ||
package tests | ||
|
||
import scala.util.control.TailCalls.{done, tailcall, TailRec} | ||
import org.scalacheck.{Arbitrary, Cogen, Gen} | ||
|
||
import Arbitrary.arbitrary | ||
|
||
import cats.laws.discipline.{DeferTests, MonadTests, SerializableTests} | ||
|
||
class TailRecSuite extends CatsSuite { | ||
|
||
implicit def tailRecArb[A: Arbitrary: Cogen]: Arbitrary[TailRec[A]] = | ||
Arbitrary( | ||
Gen.frequency( | ||
(3, arbitrary[A].map(done(_))), | ||
(1, Gen.lzy(arbitrary[(A, A => TailRec[A])].map { case (a, fn) => tailcall(fn(a)) })), | ||
(1, Gen.lzy(arbitrary[(TailRec[A], A => TailRec[A])].map { case (a, fn) => a.flatMap(fn) })) | ||
) | ||
) | ||
|
||
implicit def eqTailRec[A: Eq]: Eq[TailRec[A]] = | ||
Eq.by[TailRec[A], A](_.result) | ||
|
||
checkAll("TailRec[Int]", MonadTests[TailRec].monad[Int, Int, Int]) | ||
checkAll("Monad[TailRec]", SerializableTests.serializable(Monad[TailRec])) | ||
|
||
checkAll("TailRec[Int]", DeferTests[TailRec].defer[Int]) | ||
checkAll("Defer[TailRec]", SerializableTests.serializable(Defer[TailRec])) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Doing a search for "2.10" shows four or five other things like this we should do, but none of them look urgent.