Skip to content

Commit

Permalink
Merge branch 'master' into statet-arb
Browse files Browse the repository at this point in the history
  • Loading branch information
djspiewak committed Jun 20, 2017
2 parents 74a3404 + ca7c8c0 commit 2868cba
Show file tree
Hide file tree
Showing 43 changed files with 905 additions and 108 deletions.
2 changes: 2 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,8 @@ lazy val sharedPublishSettings = Seq(
releaseCrossBuild := true,
releaseTagName := tagName.value,
releasePublishArtifactsAction := PgpKeys.publishSigned.value,
releaseVcsSign := true,
useGpg := true, // bouncycastle has bugs with subkeys, so we use gpg instead
publishMavenStyle := true,
publishArtifact in Test := false,
pomIncludeRepository := Function.const(false),
Expand Down
8 changes: 8 additions & 0 deletions core/src/main/scala/cats/Composed.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ private[cats] trait ComposedTraverse[F[_], G[_]] extends Traverse[λ[α => F[G[
F.traverse(fga)(ga => G.traverse(ga)(f))
}

private[cats] trait ComposedNonEmptyTraverse[F[_], G[_]] extends NonEmptyTraverse[λ[α => F[G[α]]]] with ComposedTraverse[F, G] with ComposedReducible[F, G] {
def F: NonEmptyTraverse[F]
def G: NonEmptyTraverse[G]

override def nonEmptyTraverse[H[_]: Apply, A, B](fga: F[G[A]])(f: A => H[B]): H[F[G[B]]] =
F.nonEmptyTraverse(fga)(ga => G.nonEmptyTraverse(ga)(f))
}

private[cats] trait ComposedTraverseFilter[F[_], G[_]] extends TraverseFilter[λ[α => F[G[α]]]] with ComposedTraverse[F, G] {
def F: Traverse[F]
def G: TraverseFilter[G]
Expand Down
94 changes: 94 additions & 0 deletions core/src/main/scala/cats/NonEmptyTraverse.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package cats

import simulacrum.typeclass

/**
* NonEmptyTraverse, also known as Traversable1.
*
* `NonEmptyTraverse` is like a non-empty `Traverse`. In addition to the traverse and sequence
* methods it provides nonEmptyTraverse and nonEmptySequence methods which require an `Apply` instance instead of `Applicative`.
*/
@typeclass trait NonEmptyTraverse[F[_]] extends Traverse[F] with Reducible[F] { self =>

/**
* Given a function which returns a G effect, thread this effect
* through the running of this function on all the values in F,
* returning an F[B] in a G context.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> import cats.data.NonEmptyList
* scala> def countWords(words: List[String]): Map[String, Int] = words.groupBy(identity).mapValues(_.length)
* scala> NonEmptyList.of(List("How", "do", "you", "fly"), List("What", "do", "you", "do")).nonEmptyTraverse(countWords)
* res0: Map[String,cats.data.NonEmptyList[Int]] = Map(do -> NonEmptyList(1, 2), you -> NonEmptyList(1, 1))
* }}}
*/
def nonEmptyTraverse[G[_]: Apply, A, B](fa: F[A])(f: A => G[B]): G[F[B]]

/**
* Thread all the G effects through the F structure to invert the
* structure from F[G[A]] to G[F[A]].
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> import cats.data.NonEmptyList
* scala> val x = NonEmptyList.of(Map("do" -> 1, "you" -> 1), Map("do" -> 2, "you" -> 1))
* scala> val y = NonEmptyList.of(Map("How" -> 3, "do" -> 1, "you" -> 1), Map[String,Int]())
* scala> x.nonEmptySequence
* res0: Map[String,NonEmptyList[Int]] = Map(do -> NonEmptyList(1, 2), you -> NonEmptyList(1, 1))
* scala> y.nonEmptySequence
* res1: Map[String,NonEmptyList[Int]] = Map()
* }}}
*/
def nonEmptySequence[G[_]: Apply, A](fga: F[G[A]]): G[F[A]] =
nonEmptyTraverse(fga)(identity)


/**
* A nonEmptyTraverse followed by flattening the inner result.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> import cats.data.NonEmptyList
* scala> def countWords(words: List[String]): Map[String, Int] = words.groupBy(identity).mapValues(_.length)
* scala> val x = NonEmptyList.of(List("How", "do", "you", "fly"), List("What", "do", "you", "do"))
* scala> x.nonEmptyFlatTraverse(_.groupByNel(identity))
* res0: Map[String,cats.data.NonEmptyList[String]] = Map(do -> NonEmptyList(do, do, do), you -> NonEmptyList(you, you))
* }}}
*/
def nonEmptyFlatTraverse[G[_], A, B](fa: F[A])(f: A => G[F[B]])(implicit G: Apply[G], F: FlatMap[F]): G[F[B]] =
G.map(nonEmptyTraverse(fa)(f))(F.flatten)

/**
* Thread all the G effects through the F structure and flatten to invert the
* structure from F[G[F[A]]] to G[F[A]].
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> import cats.data.NonEmptyList
* scala> val x = NonEmptyList.of(Map(0 ->NonEmptyList.of(1, 2)), Map(0 -> NonEmptyList.of(3)))
* scala> val y: NonEmptyList[Map[Int, NonEmptyList[Int]]] = NonEmptyList.of(Map(), Map(1 -> NonEmptyList.of(3)))
* scala> x.nonEmptyFlatSequence
* res0: Map[Int,cats.data.NonEmptyList[Int]] = Map(0 -> NonEmptyList(1, 2, 3))
* scala> y.nonEmptyFlatSequence
* res1: Map[Int,cats.data.NonEmptyList[Int]] = Map()
* }}}
*/
def nonEmptyFlatSequence[G[_], A](fgfa: F[G[F[A]]])(implicit G: Apply[G], F: FlatMap[F]): G[F[A]] =
G.map(nonEmptyTraverse(fgfa)(identity))(F.flatten)

override def traverse[G[_] : Applicative, A, B](fa: F[A])(f: (A) => G[B]): G[F[B]] =
nonEmptyTraverse(fa)(f)

def compose[G[_]: NonEmptyTraverse]: NonEmptyTraverse[λ[α => F[G[α]]]] =
new ComposedNonEmptyTraverse[F, G] {
val F = self
val G = NonEmptyTraverse[G]
}


}
12 changes: 6 additions & 6 deletions core/src/main/scala/cats/Reducible.scala
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,17 @@ import simulacrum.typeclass
* available for `G` and want to take advantage of short-circuiting
* the traversal.
*/
def traverse1_[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Apply[G]): G[Unit] =
def nonEmptyTraverse_[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Apply[G]): G[Unit] =
G.map(reduceLeftTo(fa)(f)((x, y) => G.map2(x, f(y))((_, b) => b)))(_ => ())

/**
* Sequence `F[G[A]]` using `Apply[G]`.
*
* This method is similar to [[Foldable.sequence_]] but requires only
* an [[Apply]] instance for `G` instead of [[Applicative]]. See the
* [[traverse1_]] documentation for a description of the differences.
* [[nonEmptyTraverse_]] documentation for a description of the differences.
*/
def sequence1_[G[_], A](fga: F[G[A]])(implicit G: Apply[G]): G[Unit] =
def nonEmptySequence_[G[_], A](fga: F[G[A]])(implicit G: Apply[G]): G[Unit] =
G.map(reduceLeft(fga)((x, y) => G.map2(x, y)((_, b) => b)))(_ => ())

def toNonEmptyList[A](fa: F[A]): NonEmptyList[A] =
Expand All @@ -164,13 +164,13 @@ import simulacrum.typeclass
* scala> import cats.implicits._
* scala> import cats.data.NonEmptyList
* scala> val nel = NonEmptyList.of("a", "b", "c")
* scala> Reducible[NonEmptyList].intercalate1(nel, "-")
* scala> Reducible[NonEmptyList].nonEmptyIntercalate(nel, "-")
* res0: String = a-b-c
* scala> Reducible[NonEmptyList].intercalate1(NonEmptyList.of("a"), "-")
* scala> Reducible[NonEmptyList].nonEmptyIntercalate(NonEmptyList.of("a"), "-")
* res1: String = a
* }}}
*/
def intercalate1[A](fa: F[A], a: A)(implicit A: Semigroup[A]): A =
def nonEmptyIntercalate[A](fa: F[A], a: A)(implicit A: Semigroup[A]): A =
toNonEmptyList(fa) match {
case NonEmptyList(hd, Nil) => hd
case NonEmptyList(hd, tl) =>
Expand Down
12 changes: 12 additions & 0 deletions core/src/main/scala/cats/data/Nested.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ private[data] sealed abstract class NestedInstances extends NestedInstances0 {
new NestedTraverseFilter[F, G] {
val FG: TraverseFilter[λ[α => F[G[α]]]] = Traverse[F].composeFilter[G]
}

implicit def catsDataNonEmptyTraverseForNested[F[_]: NonEmptyTraverse, G[_]: NonEmptyTraverse]: NonEmptyTraverse[Nested[F, G, ?]] =
new NestedNonEmptyTraverse[F, G] {
val FG: NonEmptyTraverse[λ[α => F[G[α]]]] = NonEmptyTraverse[F].compose[G]
}
}

private[data] sealed abstract class NestedInstances0 extends NestedInstances1 {
Expand Down Expand Up @@ -233,6 +238,13 @@ private[data] trait NestedReducible[F[_], G[_]] extends Reducible[Nested[F, G, ?
FG.reduceRightTo(fga.value)(f)(g)
}

private[data] trait NestedNonEmptyTraverse[F[_], G[_]] extends NonEmptyTraverse[Nested[F, G, ?]] with NestedTraverse[F, G] with NestedReducible[F, G] {
def FG: NonEmptyTraverse[λ[α => F[G[α]]]]

override def nonEmptyTraverse[H[_]: Apply, A, B](fga: Nested[F, G, A])(f: A => H[B]): H[Nested[F, G, B]] =
Apply[H].map(FG.nonEmptyTraverse(fga.value)(f))(Nested(_))
}

private[data] trait NestedContravariant[F[_], G[_]] extends Contravariant[Nested[F, G, ?]] {
def FG: Contravariant[λ[α => F[G[α]]]]

Expand Down
14 changes: 11 additions & 3 deletions core/src/main/scala/cats/data/NonEmptyList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -367,9 +367,9 @@ object NonEmptyList extends NonEmptyListInstances {
private[data] sealed trait NonEmptyListInstances extends NonEmptyListInstances0 {

implicit val catsDataInstancesForNonEmptyList: SemigroupK[NonEmptyList] with Reducible[NonEmptyList]
with Comonad[NonEmptyList] with Traverse[NonEmptyList] with Monad[NonEmptyList] =
with Comonad[NonEmptyList] with NonEmptyTraverse[NonEmptyList] with Monad[NonEmptyList] =
new NonEmptyReducible[NonEmptyList, List] with SemigroupK[NonEmptyList] with Comonad[NonEmptyList]
with Traverse[NonEmptyList] with Monad[NonEmptyList] {
with Monad[NonEmptyList] with NonEmptyTraverse[NonEmptyList] {

def combineK[A](a: NonEmptyList[A], b: NonEmptyList[A]): NonEmptyList[A] =
a concat b
Expand All @@ -396,7 +396,15 @@ private[data] sealed trait NonEmptyListInstances extends NonEmptyListInstances0

def extract[A](fa: NonEmptyList[A]): A = fa.head

def traverse[G[_], A, B](fa: NonEmptyList[A])(f: A => G[B])(implicit G: Applicative[G]): G[NonEmptyList[B]] =
def nonEmptyTraverse[G[_], A, B](nel: NonEmptyList[A])(f: A => G[B])(implicit G: Apply[G]): G[NonEmptyList[B]] =
Foldable[List].reduceRightToOption[A, G[List[B]]](nel.tail)(a => G.map(f(a))(_ :: Nil)) { (a, lglb) =>
G.map2Eval(f(a), lglb)(_ :: _)
}.map {
case None => G.map(f(nel.head))(NonEmptyList(_, Nil))
case Some(gtail) => G.map2(f(nel.head), gtail)(NonEmptyList(_, _))
}.value

override def traverse[G[_], A, B](fa: NonEmptyList[A])(f: A => G[B])(implicit G: Applicative[G]): G[NonEmptyList[B]] =
fa traverse f

override def foldLeft[A, B](fa: NonEmptyList[A], b: B)(f: (B, A) => B): B =
Expand Down
14 changes: 11 additions & 3 deletions core/src/main/scala/cats/data/NonEmptyVector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,9 @@ final class NonEmptyVector[+A] private (val toVector: Vector[A]) extends AnyVal
private[data] sealed trait NonEmptyVectorInstances {

implicit val catsDataInstancesForNonEmptyVector: SemigroupK[NonEmptyVector] with Reducible[NonEmptyVector]
with Comonad[NonEmptyVector] with Traverse[NonEmptyVector] with Monad[NonEmptyVector] =
with Comonad[NonEmptyVector] with NonEmptyTraverse[NonEmptyVector] with Monad[NonEmptyVector] =
new NonEmptyReducible[NonEmptyVector, Vector] with SemigroupK[NonEmptyVector] with Comonad[NonEmptyVector]
with Traverse[NonEmptyVector] with Monad[NonEmptyVector] {
with Monad[NonEmptyVector] with NonEmptyTraverse[NonEmptyVector] {

def combineK[A](a: NonEmptyVector[A], b: NonEmptyVector[A]): NonEmptyVector[A] =
a concatNev b
Expand Down Expand Up @@ -226,7 +226,15 @@ private[data] sealed trait NonEmptyVectorInstances {

def extract[A](fa: NonEmptyVector[A]): A = fa.head

def traverse[G[_], A, B](fa: NonEmptyVector[A])(f: (A) => G[B])(implicit G: Applicative[G]): G[NonEmptyVector[B]] =
def nonEmptyTraverse[G[_], A, B](nel: NonEmptyVector[A])(f: A => G[B])(implicit G: Apply[G]): G[NonEmptyVector[B]] =
Foldable[Vector].reduceRightToOption[A, G[Vector[B]]](nel.tail)(a => G.map(f(a))(_ +: Vector.empty)) { (a, lglb) =>
G.map2Eval(f(a), lglb)(_ +: _)
}.map {
case None => G.map(f(nel.head))(NonEmptyVector(_, Vector.empty))
case Some(gtail) => G.map2(f(nel.head), gtail)(NonEmptyVector(_, _))
}.value

override def traverse[G[_], A, B](fa: NonEmptyVector[A])(f: (A) => G[B])(implicit G: Applicative[G]): G[NonEmptyVector[B]] =
G.map2Eval(f(fa.head), Always(Traverse[Vector].traverse(fa.tail)(f)))(NonEmptyVector(_, _)).value

override def foldLeft[A, B](fa: NonEmptyVector[A], b: B)(f: (B, A) => B): B =
Expand Down
25 changes: 24 additions & 1 deletion core/src/main/scala/cats/data/OneAnd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) {
def forall(p: A => Boolean)(implicit F: Foldable[F]): Boolean =
p(head) && F.forall(tail)(p)


def reduceLeft(f: (A, A) => A)(implicit F: Foldable[F]): A =
F.foldLeft(tail, head)(f)

/**
* Left-associative fold on the structure using f.
*/
Expand Down Expand Up @@ -94,7 +98,7 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) {
s"OneAnd(${A.show(head)}, ${FA.show(tail)})"
}

private[data] sealed trait OneAndInstances extends OneAndLowPriority2 {
private[data] sealed trait OneAndInstances extends OneAndLowPriority3 {

implicit def catsDataEqForOneAnd[A, F[_]](implicit A: Eq[A], FA: Eq[F[A]]): Eq[OneAnd[F, A]] =
new Eq[OneAnd[F, A]]{
Expand Down Expand Up @@ -221,4 +225,23 @@ private[data] trait OneAndLowPriority2 extends OneAndLowPriority1 {
}
}

private[data] trait OneAndLowPriority3 extends OneAndLowPriority2 {
implicit def catsDataNonEmptyTraverseForOneAnd[F[_]](implicit F: Traverse[F], F2: MonadCombine[F]): NonEmptyTraverse[OneAnd[F, ?]] =
new NonEmptyReducible[OneAnd[F, ?], F] with NonEmptyTraverse[OneAnd[F, ?]] {
def nonEmptyTraverse[G[_], A, B](fa: OneAnd[F, A])(f: (A) => G[B])(implicit G: Apply[G]): G[OneAnd[F, B]] = {
import cats.syntax.cartesian._

fa.map(a => Apply[G].map(f(a))(OneAnd(_, F2.empty[B])))(F)
.reduceLeft(((acc, a) => (acc |@| a).map((x: OneAnd[F, B], y: OneAnd[F, B]) => x.combine(y))))
}


override def traverse[G[_], A, B](fa: OneAnd[F, A])(f: (A) => G[B])(implicit G: Applicative[G]): G[OneAnd[F, B]] = {
G.map2Eval(f(fa.head), Always(F.traverse(fa.tail)(f)))(OneAnd(_, _)).value
}

def split[A](fa: OneAnd[F, A]): (A, F[A]) = (fa.head, fa.tail)
}
}

object OneAnd extends OneAndInstances
61 changes: 18 additions & 43 deletions core/src/main/scala/cats/data/ReaderWriterStateT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,6 @@ final class ReaderWriterStateT[F[_], E, S, L, A](val runF: F[(E, S) => F[(L, S,
def mapWritten[LL](f: L => LL)(implicit F: Functor[F]): ReaderWriterStateT[F, E, S, LL, A] =
transform { (l, s, a) => (f(l), s, a) }

/**
* Combine this computation with `rwsb` using `fn`. The state will be be threaded
* through the computations and the log values will be combined.
*/
def map2[B, Z](rwsb: ReaderWriterStateT[F, E, S, L, B])(fn: (A, B) => Z)(
implicit F: FlatMap[F], L: Semigroup[L]): ReaderWriterStateT[F, E, S, L, Z] =
flatMap { a =>
rwsb.map { b =>
fn(a, b)
}
}

/**
* Modify the result of the computation by feeding it into `f`, threading the state
* through the resulting computation and combining the log values.
Expand Down Expand Up @@ -343,6 +331,21 @@ private[data] sealed trait RWSTInstances extends RWSTInstances1 {
new RWSTMonadTrans[E, S, L] {
implicit def L: Monoid[L] = L0
}

implicit def catsDataProfunctorForRWST[F[_], S, L](implicit F0: Functor[F]): Profunctor[ReaderWriterStateT[F, ?, S, L, ?]] =
new RWSTProfunctor[F, S, L] {
implicit def F: Functor[F] = F0
}

implicit def catsDataBifunctorForRWST[F[_], E, S](implicit F0: Functor[F]): Bifunctor[ReaderWriterStateT[F, E, S, ?, ?]] =
new RWSTBifunctor[F, E, S] {
implicit def F: Functor[F] = F0
}

implicit def catsDataContravariantForRWST[F[_], S, L, A](implicit F0: Functor[F]): Contravariant[ReaderWriterStateT[F, ?, S, L, A]] =
new RWSTContravariant[F, S, L, A] {
implicit def F: Functor[F] = F0
}
}

private[data] sealed trait RWSTInstances1 extends RWSTInstances2 {
Expand Down Expand Up @@ -396,38 +399,17 @@ private[data] sealed trait RWSTInstances5 extends RWSTInstances6 {
}
}

private[data] sealed trait RWSTInstances6 extends RWSTInstances7 {
private[data] sealed trait RWSTInstances6 {
implicit def catsDataFunctorForRWST[F[_], E, S, L](implicit F0: Functor[F]): Functor[ReaderWriterStateT[F, E, S, L, ?]] =
new RWSTFunctor[F, E, S, L] {
implicit def F: Functor[F] = F0
}
}

private[data] sealed trait RWSTInstances7 extends RWSTInstances8 {
implicit def catsDataContravariantForRWST[F[_], S, L, A](implicit F0: Functor[F]): Contravariant[ReaderWriterStateT[F, ?, S, L, A]] =
new RWSTContravariant[F, S, L, A] {
implicit def F: Functor[F] = F0
}
}

private[data] sealed trait RWSTInstances8 extends RWSTInstances9 {
implicit def catsDataBifunctorForRWST[F[_], E, S](implicit F0: Functor[F]): Bifunctor[ReaderWriterStateT[F, E, S, ?, ?]] =
new RWSTBifunctor[F, E, S] {
implicit def F: Functor[F] = F0
}
}

private[data] sealed trait RWSTInstances9 {
implicit def catsDataProfunctorForRWST[F[_], S, L](implicit F0: Functor[F]): Profunctor[ReaderWriterStateT[F, ?, S, L, ?]] =
new RWSTProfunctor[F, S, L] {
implicit def F: Functor[F] = F0
}
}

private[data] sealed trait RWSTFunctor[F[_], E, S, L] extends Functor[ReaderWriterStateT[F, E, S, L, ?]] {
implicit def F: Functor[F]

def map[A, B](fa: ReaderWriterStateT[F, E, S, L, A])(f: A => B): ReaderWriterStateT[F, E, S, L, B] =
override def map[A, B](fa: ReaderWriterStateT[F, E, S, L, A])(f: A => B): ReaderWriterStateT[F, E, S, L, B] =
fa.map(f)
}

Expand All @@ -452,7 +434,7 @@ private[data] sealed trait RWSTProfunctor[F[_], S, L] extends Profunctor[ReaderW
fab.contramap(f).map(g)
}

private[data] sealed trait RWSTMonad[F[_], E, S, L] extends Monad[ReaderWriterStateT[F, E, S, L, ?]] {
private[data] sealed trait RWSTMonad[F[_], E, S, L] extends Monad[ReaderWriterStateT[F, E, S, L, ?]] with RWSTFunctor[F, E, S, L] {
implicit def F: Monad[F]
implicit def L: Monoid[L]

Expand All @@ -470,13 +452,6 @@ private[data] sealed trait RWSTMonad[F[_], E, S, L] extends Monad[ReaderWriterSt
}
}
}

override def map[A, B](fa: ReaderWriterStateT[F, E, S, L, A])(f: A => B): ReaderWriterStateT[F, E, S, L, B] =
fa.map(f)

override def map2[A, B, Z](fa: ReaderWriterStateT[F, E, S, L, A],
fb: ReaderWriterStateT[F, E, S, L, B])(f: (A, B) => Z): ReaderWriterStateT[F, E, S, L, Z] =
fa.map2(fb)(f)
}

private[data] sealed trait RWSTMonadState[F[_], E, S, L]
Expand Down
Loading

0 comments on commit 2868cba

Please sign in to comment.