-
-
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
Treat Stream and LazyList as different types #2983
Changes from 6 commits
4edcd9e
73c389f
dd79248
d843f04
6f8658b
67dc634
40333b2
c316ca2
7806c4c
e8dcc68
66742d7
f9ab0e2
bf10981
ae7b6e5
9b28588
f80d9ab
fd972c5
7e52796
a2cdc6b
6a1c334
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package cats | ||
package data | ||
|
||
import scala.annotation.tailrec | ||
import scala.collection.mutable.Builder | ||
|
||
abstract private[data] class OneAndLowPriority4 { | ||
implicit val catsDataComonadForNonEmptyStream: Comonad[OneAnd[Stream, *]] = | ||
new Comonad[OneAnd[Stream, *]] { | ||
def coflatMap[A, B](fa: OneAnd[Stream, A])(f: OneAnd[Stream, A] => B): OneAnd[Stream, B] = { | ||
@tailrec def consume(as: Stream[A], buf: Builder[B, Stream[B]]): Stream[B] = | ||
if (as.isEmpty) buf.result | ||
else { | ||
val tail = as.tail | ||
consume(tail, buf += f(OneAnd(as.head, tail))) | ||
} | ||
OneAnd(f(fa), consume(fa.tail, Stream.newBuilder)) | ||
} | ||
|
||
def extract[A](fa: OneAnd[Stream, A]): A = | ||
fa.head | ||
|
||
def map[A, B](fa: OneAnd[Stream, A])(f: A => B): OneAnd[Stream, B] = | ||
fa.map(f)(cats.instances.stream.catsStdInstancesForStream) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,15 @@ | ||
package cats | ||
|
||
package data | ||
|
||
abstract private[data] class ScalaVersionSpecificPackage | ||
import kernel.compat.scalaVersionSpecific._ | ||
|
||
abstract private[data] class ScalaVersionSpecificPackage { | ||
type NonEmptyStream[A] = OneAnd[Stream, A] | ||
|
||
def NonEmptyStream[A](head: A, tail: Stream[A] = Stream.empty): NonEmptyStream[A] = | ||
OneAnd(head, tail) | ||
|
||
@suppressUnusedImportWarningForScalaVersionSpecific | ||
def NonEmptyStream[A](head: A, tail: A*): NonEmptyStream[A] = | ||
OneAnd(head, tail.toStream) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package cats | ||
package instances | ||
|
||
import cats.data._ | ||
import cats.kernel.Semigroup | ||
import cats.syntax.either._ | ||
import cats.{~>, Applicative, Apply, FlatMap, Functor, Monad, NonEmptyParallel, Parallel} | ||
import kernel.compat.scalaVersionSpecific._ | ||
|
||
@suppressUnusedImportWarningForScalaVersionSpecific | ||
trait ParallelInstances extends ParallelInstances1 { | ||
implicit def catsParallelForEitherValidated[E: Semigroup]: Parallel[Either[E, *], Validated[E, *]] = | ||
new Parallel[Either[E, *], Validated[E, *]] { | ||
|
||
def applicative: Applicative[Validated[E, *]] = Validated.catsDataApplicativeErrorForValidated | ||
def monad: Monad[Either[E, *]] = cats.instances.either.catsStdInstancesForEither | ||
|
||
def sequential: Validated[E, *] ~> Either[E, *] = | ||
λ[Validated[E, *] ~> Either[E, *]](_.toEither) | ||
|
||
def parallel: Either[E, *] ~> Validated[E, *] = | ||
λ[Either[E, *] ~> Validated[E, *]](_.toValidated) | ||
} | ||
|
||
implicit def catsParallelForOptionTNestedOption[F[_], M[_]]( | ||
implicit P: Parallel[M, F] | ||
): Parallel[OptionT[M, *], Nested[F, Option, *]] = new Parallel[OptionT[M, *], Nested[F, Option, *]] { | ||
|
||
implicit val appF: Applicative[F] = P.applicative | ||
implicit val monadM: Monad[M] = P.monad | ||
implicit val appOption: Applicative[Option] = cats.instances.option.catsStdInstancesForOption | ||
|
||
def applicative: Applicative[Nested[F, Option, *]] = cats.data.Nested.catsDataApplicativeForNested[F, Option] | ||
|
||
def monad: Monad[OptionT[M, *]] = cats.data.OptionT.catsDataMonadErrorMonadForOptionT[M] | ||
|
||
def sequential: Nested[F, Option, *] ~> OptionT[M, *] = | ||
λ[Nested[F, Option, *] ~> OptionT[M, *]](nested => OptionT(P.sequential(nested.value))) | ||
|
||
def parallel: OptionT[M, *] ~> Nested[F, Option, *] = | ||
λ[OptionT[M, *] ~> Nested[F, Option, *]](optT => Nested(P.parallel(optT.value))) | ||
} | ||
|
||
implicit def catsStdNonEmptyParallelForZipList[A]: NonEmptyParallel[List, ZipList] = | ||
new NonEmptyParallel[List, ZipList] { | ||
|
||
def flatMap: FlatMap[List] = cats.instances.list.catsStdInstancesForList | ||
def apply: Apply[ZipList] = ZipList.catsDataCommutativeApplyForZipList | ||
|
||
def sequential: ZipList ~> List = | ||
λ[ZipList ~> List](_.value) | ||
|
||
def parallel: List ~> ZipList = | ||
λ[List ~> ZipList](v => new ZipList(v)) | ||
} | ||
|
||
implicit def catsStdNonEmptyParallelForZipVector[A]: NonEmptyParallel[Vector, ZipVector] = | ||
new NonEmptyParallel[Vector, ZipVector] { | ||
|
||
def flatMap: FlatMap[Vector] = cats.instances.vector.catsStdInstancesForVector | ||
def apply: Apply[ZipVector] = ZipVector.catsDataCommutativeApplyForZipVector | ||
|
||
def sequential: ZipVector ~> Vector = | ||
λ[ZipVector ~> Vector](_.value) | ||
|
||
def parallel: Vector ~> ZipVector = | ||
λ[Vector ~> ZipVector](v => new ZipVector(v)) | ||
} | ||
|
||
implicit def catsStdParallelForZipStream[A]: Parallel[Stream, ZipStream] = | ||
new Parallel[Stream, ZipStream] { | ||
|
||
def monad: Monad[Stream] = cats.instances.stream.catsStdInstancesForStream | ||
def applicative: Applicative[ZipStream] = ZipStream.catsDataAlternativeForZipStream | ||
|
||
def sequential: ZipStream ~> Stream = | ||
λ[ZipStream ~> Stream](_.value) | ||
|
||
def parallel: Stream ~> ZipStream = | ||
λ[Stream ~> ZipStream](v => new ZipStream(v)) | ||
} | ||
|
||
implicit def catsParallelForEitherTNestedParallelValidated[F[_], M[_], E: Semigroup]( | ||
implicit P: Parallel[M, F] | ||
): Parallel[EitherT[M, E, *], Nested[F, Validated[E, *], *]] = | ||
new Parallel[EitherT[M, E, *], Nested[F, Validated[E, *], *]] { | ||
|
||
implicit val appF: Applicative[F] = P.applicative | ||
implicit val monadM: Monad[M] = P.monad | ||
implicit val appValidated: Applicative[Validated[E, *]] = Validated.catsDataApplicativeErrorForValidated | ||
implicit val monadEither: Monad[Either[E, *]] = cats.instances.either.catsStdInstancesForEither | ||
|
||
def applicative: Applicative[Nested[F, Validated[E, *], *]] = | ||
cats.data.Nested.catsDataApplicativeForNested[F, Validated[E, *]] | ||
|
||
def monad: Monad[EitherT[M, E, *]] = cats.data.EitherT.catsDataMonadErrorForEitherT | ||
|
||
def sequential: Nested[F, Validated[E, *], *] ~> EitherT[M, E, *] = | ||
λ[Nested[F, Validated[E, *], *] ~> EitherT[M, E, *]] { nested => | ||
val mva = P.sequential(nested.value) | ||
EitherT(Functor[M].map(mva)(_.toEither)) | ||
} | ||
|
||
def parallel: EitherT[M, E, *] ~> Nested[F, Validated[E, *], *] = | ||
λ[EitherT[M, E, *] ~> Nested[F, Validated[E, *], *]] { eitherT => | ||
val fea = P.parallel(eitherT.value) | ||
Nested(Functor[F].map(fea)(_.toValidated)) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,11 +6,9 @@ import cats.syntax.show._ | |
import scala.annotation.tailrec | ||
|
||
/** | ||
* For cross compile with backward compatibility | ||
* Needed only to avoid some version-specific code in `cats.instances.all`. | ||
*/ | ||
trait LazyListInstances extends StreamInstances with StreamInstancesBinCompat0 { | ||
val catsStdInstancesForLazyList = catsStdInstancesForStream | ||
} | ||
private[instances] trait LazyListInstances | ||
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. Is this still needed? 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. If we don't want two copies of (I guess you could argue that we have two copies of everything else at this point so we might as well do it here.) 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. didn't you already add version specific copies for cats/instances/package.scala? 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, but the definition of 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. Ah i see. I didn't see you were able to deprecate all the methods in 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. Sure, I can go ahead and do this. |
||
|
||
trait StreamInstances extends cats.kernel.instances.StreamInstances { | ||
|
||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package cats | ||
package data | ||
|
||
import scala.annotation.tailrec | ||
import scala.collection.mutable.Builder | ||
|
||
abstract private[data] class OneAndLowPriority4 { | ||
@deprecated("2.0.0-RC2", "Use catsDataComonadForNonEmptyLazyList") | ||
implicit def catsDataComonadForNonEmptyStream: Comonad[OneAnd[Stream, *]] = | ||
new Comonad[OneAnd[Stream, *]] { | ||
def coflatMap[A, B](fa: OneAnd[Stream, A])(f: OneAnd[Stream, A] => B): OneAnd[Stream, B] = { | ||
@tailrec def consume(as: Stream[A], buf: Builder[B, Stream[B]]): Stream[B] = | ||
if (as.isEmpty) buf.result | ||
else { | ||
val tail = as.tail | ||
consume(tail, buf += f(OneAnd(as.head, tail))) | ||
} | ||
OneAnd(f(fa), consume(fa.tail, Stream.newBuilder)) | ||
} | ||
|
||
def extract[A](fa: OneAnd[Stream, A]): A = | ||
fa.head | ||
|
||
def map[A, B](fa: OneAnd[Stream, A])(f: A => B): OneAnd[Stream, B] = | ||
fa.map(f)(cats.instances.stream.catsStdInstancesForStream) | ||
} | ||
|
||
implicit val catsDataComonadForNonEmptyLazyList: Comonad[OneAnd[LazyList, *]] = | ||
new Comonad[OneAnd[LazyList, *]] { | ||
def coflatMap[A, B](fa: OneAnd[LazyList, A])(f: OneAnd[LazyList, A] => B): OneAnd[LazyList, B] = { | ||
@tailrec def consume(as: LazyList[A], buf: Builder[B, LazyList[B]]): LazyList[B] = | ||
if (as.isEmpty) buf.result | ||
else { | ||
val tail = as.tail | ||
consume(tail, buf += f(OneAnd(as.head, tail))) | ||
} | ||
OneAnd(f(fa), consume(fa.tail, LazyList.newBuilder)) | ||
} | ||
|
||
def extract[A](fa: OneAnd[LazyList, A]): A = | ||
fa.head | ||
|
||
def map[A, B](fa: OneAnd[LazyList, A])(f: A => B): OneAnd[LazyList, B] = | ||
fa.map(f)(cats.instances.lazyList.catsStdInstancesForLazyList) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,19 @@ | ||
package cats | ||
|
||
package data | ||
|
||
import kernel.compat.scalaVersionSpecific._ | ||
|
||
abstract private[data] class ScalaVersionSpecificPackage { | ||
type NonEmptyLazyList[+A] = NonEmptyLazyList.Type[A] | ||
@deprecated("2.0.0-RC2", "Use NonEmptyLazyList") | ||
type NonEmptyStream[A] = OneAnd[Stream, A] | ||
|
||
@deprecated("2.0.0-RC2", "Use NonEmptyLazyList") | ||
def NonEmptyStream[A](head: A, tail: Stream[A]): NonEmptyStream[A] = | ||
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. Note that we can't have the default argument here that we have on 2.11 and 2.12, since it results in a deprecation warning (which is clearly a compiler bug). |
||
OneAnd(head, tail) | ||
|
||
@suppressUnusedImportWarningForScalaVersionSpecific | ||
@deprecated("2.0.0-RC2", "Use NonEmptyLazyList") | ||
def NonEmptyStream[A](head: A, tail: A*): NonEmptyStream[A] = | ||
OneAnd(head, tail.toStream) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package cats | ||
package data | ||
|
||
class ZipLazyList[A](val value: LazyList[A]) extends AnyVal | ||
|
||
object ZipLazyList { | ||
|
||
def apply[A](value: LazyList[A]): ZipLazyList[A] = new ZipLazyList(value) | ||
|
||
implicit val catsDataAlternativeForZipLazyList: Alternative[ZipLazyList] with CommutativeApplicative[ZipLazyList] = | ||
new Alternative[ZipLazyList] with CommutativeApplicative[ZipLazyList] { | ||
def pure[A](x: A): ZipLazyList[A] = new ZipLazyList(LazyList.continually(x)) | ||
|
||
override def map[A, B](fa: ZipLazyList[A])(f: (A) => B): ZipLazyList[B] = | ||
ZipLazyList(fa.value.map(f)) | ||
|
||
def ap[A, B](ff: ZipLazyList[A => B])(fa: ZipLazyList[A]): ZipLazyList[B] = | ||
ZipLazyList(ff.value.lazyZip(fa.value).map(_.apply(_))) | ||
|
||
override def product[A, B](fa: ZipLazyList[A], fb: ZipLazyList[B]): ZipLazyList[(A, B)] = | ||
ZipLazyList(fa.value.zip(fb.value)) | ||
|
||
def empty[A]: ZipLazyList[A] = ZipLazyList(LazyList.empty[A]) | ||
|
||
def combineK[A](x: ZipLazyList[A], y: ZipLazyList[A]): ZipLazyList[A] = | ||
ZipLazyList(cats.instances.lazyList.catsStdInstancesForLazyList.combineK(x.value, y.value)) | ||
} | ||
|
||
implicit def catsDataEqForZipLazyList[A: Eq]: Eq[ZipLazyList[A]] = | ||
Eq.by((_: ZipLazyList[A]).value)(cats.kernel.instances.lazyList.catsKernelStdEqForLazyList[A]) | ||
} |
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.
This is necessary because we now have deprecation warnings for
Stream
on 2.13.