-
-
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
Merged
travisbrown
merged 20 commits into
typelevel:master
from
travisbrown:topic/stream-instances
Aug 22, 2019
Merged
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
4edcd9e
Remove cats.instances.stream and introduce cats.kernel.instances.lazy…
travisbrown 73c389f
Merge branch 'master' into topic/stream-instances
travisbrown dd79248
Merge branch 'master' into topic/stream-instances
travisbrown d843f04
Reinstate stream instances on 2.13
travisbrown 6f8658b
Don't alias LazyList to Stream pre-2.13
travisbrown 67dc634
Fix duplicate test names
travisbrown 40333b2
Don't use scalaVersionSpecific helpers in version-specific code
travisbrown c316ca2
Add LazyList tests for kernel
travisbrown 7806c4c
Parallel laws checking for NonEmptyLazyList
travisbrown e8dcc68
Provide Parallel instance for NonEmptyLazyList via OneAnd and ZipLazy…
travisbrown 66742d7
Avoid LazyListInstances in non-2.13 code
travisbrown f9ab0e2
Merge branch 'master' into topic/stream-instances
travisbrown bf10981
Desperate attempt to fix Travis CI weirdness
travisbrown ae7b6e5
Revert "Desperate attempt to fix Travis CI weirdness"
travisbrown 9b28588
Another desperate attempt
travisbrown f80d9ab
Revert "Another desperate attempt"
travisbrown fd972c5
Switch to OpenJDK 8
travisbrown 7e52796
Reinstate Stream tests
travisbrown a2cdc6b
...with the right types this time
travisbrown 6a1c334
Add regression tests for #513 for LazyList on 2.13
travisbrown File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
26 changes: 26 additions & 0 deletions
26
core/src/main/scala-2.12-/cats/data/OneAndLowPriority4.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
11 changes: 9 additions & 2 deletions
11
core/src/main/scala-2.12-/cats/data/ScalaVersionSpecificPackage.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,12 @@ | ||
package cats | ||
|
||
package data | ||
|
||
abstract private[data] class ScalaVersionSpecificPackage | ||
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) | ||
|
||
def NonEmptyStream[A](head: A, tail: A*): NonEmptyStream[A] = | ||
OneAnd(head, tail.toStream) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package cats | ||
package data | ||
|
||
class ZipStream[A](val value: Stream[A]) extends AnyVal | ||
|
||
object ZipStream { | ||
|
||
def apply[A](value: Stream[A]): ZipStream[A] = new ZipStream(value) | ||
|
||
implicit val catsDataAlternativeForZipStream: Alternative[ZipStream] with CommutativeApplicative[ZipStream] = | ||
new Alternative[ZipStream] with CommutativeApplicative[ZipStream] { | ||
def pure[A](x: A): ZipStream[A] = new ZipStream(Stream.continually(x)) | ||
|
||
override def map[A, B](fa: ZipStream[A])(f: (A) => B): ZipStream[B] = | ||
ZipStream(fa.value.map(f)) | ||
|
||
def ap[A, B](ff: ZipStream[A => B])(fa: ZipStream[A]): ZipStream[B] = | ||
ZipStream((ff.value, fa.value).zipped.map(_.apply(_))) | ||
|
||
override def product[A, B](fa: ZipStream[A], fb: ZipStream[B]): ZipStream[(A, B)] = | ||
ZipStream(fa.value.zip(fb.value)) | ||
|
||
def empty[A]: ZipStream[A] = ZipStream(Stream.empty[A]) | ||
|
||
def combineK[A](x: ZipStream[A], y: ZipStream[A]): ZipStream[A] = | ||
ZipStream(cats.instances.stream.catsStdInstancesForStream.combineK(x.value, y.value)) | ||
} | ||
|
||
implicit def catsDataEqForZipStream[A: Eq]: Eq[ZipStream[A]] = | ||
Eq.by((_: ZipStream[A]).value)(cats.kernel.instances.stream.catsKernelStdEqForStream[A]) | ||
} |
108 changes: 108 additions & 0 deletions
108
core/src/main/scala-2.12-/cats/instances/ScalaVersionSpecificParallelInstances.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package cats | ||
package instances | ||
|
||
import cats.data._ | ||
import cats.kernel.Semigroup | ||
import cats.syntax.either._ | ||
import cats.{~>, Applicative, Apply, FlatMap, Functor, Monad, NonEmptyParallel, Parallel} | ||
|
||
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)) | ||
} | ||
} | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
core/src/main/scala-2.13+/cats/data/OneAndLowPriority4.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
11 changes: 10 additions & 1 deletion
11
core/src/main/scala-2.13+/cats/data/ScalaVersionSpecificPackage.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,16 @@ | ||
package cats | ||
|
||
package data | ||
|
||
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) | ||
|
||
@deprecated("2.0.0-RC2", "Use NonEmptyLazyList") | ||
def NonEmptyStream[A](head: A, tail: A*): NonEmptyStream[A] = | ||
OneAnd(head, tail.toStream) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.