Skip to content

Commit

Permalink
Merge branch 'master' into add-unordered-classes
Browse files Browse the repository at this point in the history
  • Loading branch information
kailuowang authored Nov 9, 2017
2 parents 5f4d41f + 6863f3f commit cd2e1f5
Show file tree
Hide file tree
Showing 58 changed files with 638 additions and 568 deletions.
19 changes: 19 additions & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ possible:
* Aldo Stracquadanio
* Alejandro Gómez
* Alessandro Lacava
* Alejandro Marín E.
* Alexandru Nedelcu
* Alexander Semenov
* Alexey Levan
Expand All @@ -37,9 +38,11 @@ possible:
* Ben Hutchison
* Benjamin Thuillier
* Binh Nguyen
* Bjørn Madsen
* Bobby Rauchenberg
* Brendan McAdams
* Brian McKenna
* Bryan Tan
* Chris Birchall
* Cody Allen
* Colt Frederickson
Expand All @@ -53,11 +56,13 @@ possible:
* Dave Rostron
* David Allsopp
* David Gregory
* David R. Bild
* Denis Mikhaylov
* Denis
* Derek Wickern
* Diego Esteban Alonso Blas
* Earl St Sauver
* Edd Steel
* Eric Torreborre
* Erik LaBianca
* Erik Osheim
Expand All @@ -67,12 +72,15 @@ possible:
* Fabio Labella
* Feynman Liang
* Frank S. Thomas
* Gabriele Petronella
* Giulio De Luise
* Greg Pfeil
* Guillaume Massé
* Hamish Dickson
* Harrison Houghton
* Ian McIntosh
* ImLiar
* Ionuț G. Stan
* Israel Pérez González
* Itamar Ravid
* Jan-Hendrik Zab
Expand All @@ -88,6 +96,7 @@ possible:
* Juan Pedro Moreno
* Julien Richard-Foy
* Julien Truffaut
* Jun Tomioka
* Kailuo Wang
* Kenji Yoshida
* Leandro Bolivar
Expand All @@ -107,6 +116,7 @@ possible:
* Matthias Lüneberg
* Max Worgan
* Merlin Göttlinger
* Michael Ledin
* Michael Pilquist
* Mike Curry
* Miles Sabin
Expand All @@ -127,6 +137,8 @@ possible:
* Rafa Paradela
* Raúl Raja Martínez
* RawToast
* Raymond Tay
* Richard Imaoka
* Richard Miller
* Rintcius Blok
* Rob Norris
Expand All @@ -136,26 +148,33 @@ possible:
* Ryan Case
* Sam Ritchie
* Sarunas Valaskevicius
* Sho Kohara
* Shohei Kamimori
* Shunsuke Otani
* Simeon H. K. Fitch
* Sinisa Louc
* Stephen Carman
* Stephen Judkins
* Stew O'Connor
* Suhas Gaddam
* Sumedh Mungee
* Takayuki Sakai
* Taylor Brown
* Tom Switzer
* Tomas Mikula
* Tongfei Chen
* Travis Brown
* Trond Bjerkestrand
* Tya
* ven
* Vladimir Samoylov
* Wedens
* Xavier Fernández Salas
* Yosef Fertel
* Yilin Wei
* Zach Abbott
* zainab-ali
* Ziyang Liu

Cats has been heavily inspired by many libraries, including [Scalaz](https://github.com/scalaz/scalaz),
Haskell's [Prelude](https://hackage.haskell.org/package/base-4.9.0.0/docs/Prelude.html), and others.
Expand Down
183 changes: 183 additions & 0 deletions CHANGES.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ addSbtPlugin("org.lyranthe.sbt" % "partial-unification" % "1.1.0")
And then create the cats dependency, by adding the following to your `build.sbt`:

```scala
libraryDependencies += "org.typelevel" %% "cats-core" % "1.0.0-MF"
libraryDependencies += "org.typelevel" %% "cats-core" % "1.0.0-RC1"
```

This will pull in the cats-core module. If you require some other
Expand All @@ -52,13 +52,13 @@ functionality, you can pick-and-choose from amongst these modules
* `cats-laws`: Laws for testing type class instances.
* `cats-free`: Free structures such as the free monad, and supporting type classes.
* `cats-testkit`: lib for writing tests for type class instances using laws.
* `alleycats-core`: cats instances and classes which are not lawful.

There are several other cats modules that are in separate repos so that they can
maintain independent release cycles.

* [`cats-effect`](https://github.com/typelevel/cats-effect): standard `IO` type together with `Sync`, `Async` and `Effect` type classes
* [`cats-mtl`](https://github.com/typelevel/cats-mtl): transformer typeclasses for cats' Monads, Applicatives and Functors.
* [`alleycats`](https://github.com/non/alleycats): cats instances and classes which are not lawful.
* [`mouse`](https://github.com/typelevel/mouse): a small companion to cats that provides convenient syntax (aka extension methods)


Expand Down
401 changes: 16 additions & 385 deletions build.sbt

Large diffs are not rendered by default.

51 changes: 49 additions & 2 deletions core/src/main/scala/cats/Foldable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,29 @@ import simulacrum.typeclass
@typeclass trait Foldable[F[_]] extends UnorderedFoldable[F] { self =>

/**
* Left associative fold on 'F' using the function 'f'.
*/
* Left associative fold on 'F' using the function 'f'.
*
* Example:
* {{{
* scala> import cats.Foldable, cats.implicits._
* scala> val fa = Option(1)
*
* Folding by addition to zero:
* scala> Foldable[Option].foldLeft(fa, Option(0))((a, n) => a.map(_ + n))
* res0: Option[Int] = Some(1)
* }}}
*
* With syntax extensions, `foldLeft` can be used like:
* {{{
* Folding `Option` with addition from zero:
* scala> fa.foldLeft(Option(0))((a, n) => a.map(_ + n))
* res1: Option[Int] = Some(1)
*
* There's also an alias `foldl` which is equivalent:
* scala> fa.foldl(Option(0))((a, n) => a.map(_ + n))
* res2: Option[Int] = Some(1)
* }}}
*/
def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B


Expand All @@ -46,6 +67,32 @@ import simulacrum.typeclass
*
* For more detailed information about how this method works see the
* documentation for `Eval[_]`.
*
* Example:
* {{{
* scala> import cats.Foldable, cats.Eval, cats.implicits._
* scala> val fa = Option(1)
*
* Folding by addition to zero:
* scala> val folded1 = Foldable[Option].foldRight(fa, Eval.now(0))((n, a) => a.map(_ + n))
* Since `foldRight` yields a lazy computation, we need to force it to inspect the result:
* scala> folded1.value
* res0: Int = 1
*
* With syntax extensions, we can write the same thing like this:
* scala> val folded2 = fa.foldRight(Eval.now(0))((n, a) => a.map(_ + n))
* scala> folded2.value
* res1: Int = 1
*
* Unfortunately, since `foldRight` is defined on many collections - this
* extension clashes with the operation defined in `Foldable`.
*
* To get past this and make sure you're getting the lazy `foldRight` defined
* in `Foldable`, there's an alias `foldr`:
* scala> val folded3 = fa.foldr(Eval.now(0))((n, a) => a.map(_ + n))
* scala> folded3.value
* res1: Int = 1
* }}}
*/
def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B]

Expand Down
7 changes: 6 additions & 1 deletion core/src/main/scala/cats/data/EitherK.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ final case class EitherK[F[_], G[_], A](run: Either[F[A], G[A]]) {
def map[B](f: A => B)(implicit F: Functor[F], G: Functor[G]): EitherK[F, G, B] =
EitherK(run.bimap(F.lift(f), G.lift(f)))

/**
* Modify the right side context `G` using transformation `f`.
*/
def mapK[H[_]](f: G ~> H): EitherK[F, H, A] =
EitherK(run.map(f.apply))

def coflatMap[B](f: EitherK[F, G, A] => B)(implicit F: CoflatMap[F], G: CoflatMap[G]): EitherK[F, G, B] =
EitherK(
run.bimap(a => F.coflatMap(a)(x => f(leftc(x))), a => G.coflatMap(a)(x => f(rightc(x))))
Expand Down Expand Up @@ -234,4 +240,3 @@ private[data] trait EitherKComonad[F[_], G[_]] extends Comonad[EitherK[F, G, ?]]
def extract[A](p: EitherK[F, G, A]): A =
p.extract
}

5 changes: 5 additions & 0 deletions core/src/main/scala/cats/data/EitherT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {

def map[D](f: B => D)(implicit F: Functor[F]): EitherT[F, A, D] = bimap(identity, f)

/**
* Modify the context `F` using transformation `f`.
*/
def mapK[G[_]](f: F ~> G): EitherT[G, A, B] = EitherT[G, A, B](f(value))

def semiflatMap[D](f: B => F[D])(implicit F: Monad[F]): EitherT[F, A, D] =
flatMap(b => EitherT.right(f(b)))

Expand Down
6 changes: 6 additions & 0 deletions core/src/main/scala/cats/data/Func.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ sealed abstract class Func[F[_], A, B] { self =>
def run: A => F[B]
def map[C](f: B => C)(implicit FF: Functor[F]): Func[F, A, C] =
Func.func(a => FF.map(self.run(a))(f))

/**
* Modify the context `F` using transformation `f`.
*/
def mapK[G[_]](f: F ~> G): Func[G, A, B] =
Func.func(run andThen f.apply)
}

object Func extends FuncInstances {
Expand Down
10 changes: 8 additions & 2 deletions core/src/main/scala/cats/data/IdT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ final case class IdT[F[_], A](value: F[A]) {
def map[B](f: A => B)(implicit F: Functor[F]): IdT[F, B] =
IdT(F.map(value)(f))

/**
* Modify the context `F` using transformation `f`.
*/
def mapK[G[_]](f: F ~> G): IdT[G, A] =
IdT[G, A](f(value))

def flatMap[B](f: A => IdT[F, B])(implicit F: FlatMap[F]): IdT[F, B] =
IdT(F.flatMap(value)(f.andThen(_.value)))

Expand Down Expand Up @@ -151,7 +157,7 @@ private[data] sealed abstract class IdTInstances0 extends IdTInstances1 {
new IdTTraverse[F] { implicit val F0: Traverse[F] = F }

implicit def catsDataEqForIdT[F[_], A](implicit F: Eq[F[A]]): Eq[IdT[F, A]] =
F.on(_.value)
Eq.by[IdT[F, A], F[A]](_.value)
}

private[data] sealed abstract class IdTInstances extends IdTInstances0 {
Expand All @@ -160,7 +166,7 @@ private[data] sealed abstract class IdTInstances extends IdTInstances0 {
new IdTNonEmptyTraverse[F] { implicit val F0: NonEmptyTraverse[F] = F }

implicit def catsDataOrderForIdT[F[_], A](implicit F: Order[F[A]]): Order[IdT[F, A]] =
F.on(_.value)
Order.by[IdT[F, A], F[A]](_.value)

implicit def catsDataShowForIdT[F[_], A](implicit F: Show[F[A]]): Show[IdT[F, A]] =
Contravariant[Show].contramap(F)(_.value)
Expand Down
7 changes: 7 additions & 0 deletions core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ final class IndexedReaderWriterStateT[F[_], E, L, SA, SB, A](val runF: F[(E, SA)
def map[B](f: A => B)(implicit F: Functor[F]): IndexedReaderWriterStateT[F, E, L, SA, SB, B] =
transform { (l, s, a) => (l, s, f(a)) }

/**
* Modify the context `F` using transformation `f`.
*/
def mapK[G[_]](f: F ~> G)(implicit F: Functor[F]): IndexedReaderWriterStateT[G, E, L, SA, SB, A] =
IndexedReaderWriterStateT.applyF(
f(F.map(runF)(rwsa => (e, sa) => f(rwsa(e, sa)))))

/**
* Modify the resulting state using `f` and the resulting value using `g`.
*/
Expand Down
7 changes: 7 additions & 0 deletions core/src/main/scala/cats/data/IndexedStateT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ final class IndexedStateT[F[_], SA, SB, A](val runF: F[SA => F[(SB, A)]]) extend
def map[B](f: A => B)(implicit F: Functor[F]): IndexedStateT[F, SA, SB, B] =
transform { case (s, a) => (s, f(a)) }

/**
* Modify the context `F` using transformation `f`.
*/
def mapK[G[_]](f: F ~> G)(implicit F: Functor[F]): IndexedStateT[G, SA, SB, A] =
IndexedStateT.applyF(
f(F.map(runF)(_.andThen(fsa => f(fsa)))))

def contramap[S0](f: S0 => SA)(implicit F: Functor[F]): IndexedStateT[F, S0, SB, A] =
IndexedStateT.applyF {
F.map(runF) { safsba =>
Expand Down
13 changes: 10 additions & 3 deletions core/src/main/scala/cats/data/Kleisli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ final case class Kleisli[F[_], A, B](run: A => F[B]) { self =>
def mapF[N[_], C](f: F[B] => N[C]): Kleisli[N, A, C] =
Kleisli(run andThen f)

/**
* Modify the context `F` using transformation `f`.
*/
def mapK[G[_]](f: F ~> G): Kleisli[G, A, B] =
Kleisli[G, A, B](run andThen f.apply)

def flatMap[C](f: B => Kleisli[F, A, C])(implicit F: FlatMap[F]): Kleisli[F, A, C] =
Kleisli((r: A) => F.flatMap[B, C](run(r))((b: B) => f(b).run(r)))

Expand Down Expand Up @@ -48,8 +54,9 @@ final case class Kleisli[F[_], A, B](run: A => F[B]) { self =>
def local[AA](f: AA => A): Kleisli[F, AA, B] =
Kleisli(f.andThen(run))

@deprecated("Use mapK", "1.0.0")
def transform[G[_]](f: FunctionK[F, G]): Kleisli[G, A, B] =
Kleisli(a => f(run(a)))
mapK(f)

def lower(implicit F: Applicative[F]): Kleisli[F, A, F[B]] =
Kleisli(a => F.pure(run(a)))
Expand Down Expand Up @@ -148,10 +155,10 @@ private[data] sealed abstract class KleisliInstances1 extends KleisliInstances2
def monad: Monad[Kleisli[M, A, ?]] = catsDataMonadForKleisli

def sequential: Kleisli[F, A, ?] ~> Kleisli[M, A, ?] =
λ[Kleisli[F, A, ?] ~> Kleisli[M, A, ?]](_.transform(P.sequential))
λ[Kleisli[F, A, ?] ~> Kleisli[M, A, ?]](_.mapK(P.sequential))

def parallel: Kleisli[M, A, ?] ~> Kleisli[F, A, ?] =
λ[Kleisli[M, A, ?] ~> Kleisli[F, A, ?]](_.transform(P.parallel))
λ[Kleisli[M, A, ?] ~> Kleisli[F, A, ?]](_.mapK(P.parallel))
}
}

Expand Down
12 changes: 10 additions & 2 deletions core/src/main/scala/cats/data/Nested.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,21 @@ package data
* res1: List[Option[String]] = List(Some(2), None)
* }}}
*/
final case class Nested[F[_], G[_], A](value: F[G[A]])
final case class Nested[F[_], G[_], A](value: F[G[A]]) {

/**
* Modify the context `F` using transformation `f`.
*/
def mapK[H[_]](f: F ~> H): Nested[H, G, A] =
Nested(f(value))

}

object Nested extends NestedInstances

private[data] sealed abstract class NestedInstances extends NestedInstances0 {
implicit def catsDataEqForNested[F[_], G[_], A](implicit FGA: Eq[F[G[A]]]): Eq[Nested[F, G, A]] =
FGA.on(_.value)
Eq.by[Nested[F, G, A], F[G[A]]](_.value)

implicit def catsDataNonEmptyTraverseForNested[F[_]: NonEmptyTraverse, G[_]: NonEmptyTraverse]: NonEmptyTraverse[Nested[F, G, ?]] =
new NestedNonEmptyTraverse[F, G] {
Expand Down
13 changes: 13 additions & 0 deletions core/src/main/scala/cats/data/NonEmptyList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,19 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) {
def prepend[AA >: A](a: AA): NonEmptyList[AA] =
NonEmptyList(a, head :: tail)

/**
* Alias for concat
*
* {{{
* scala> import cats.data.NonEmptyList
* scala> val nel = NonEmptyList.of(1, 2, 3)
* scala> nel ::: NonEmptyList.of(4, 5)
* res0: cats.data.NonEmptyList[Int] = NonEmptyList(1, 2, 3, 4, 5)
* }}}
*/
def :::[AA >: A](other: NonEmptyList[AA]): NonEmptyList[AA] =
other.concatNel(this)

/**
* Remove elements not matching the predicate
*
Expand Down
12 changes: 12 additions & 0 deletions core/src/main/scala/cats/data/NonEmptyVector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ final class NonEmptyVector[+A] private (val toVector: Vector[A]) extends AnyVal
*/
def ++[AA >: A](other: Vector[AA]): NonEmptyVector[AA] = concat(other)

/**
* Append this NEV to another NEV, producing a new `NonEmptyVector`.
*
* {{{
* scala> import cats.data.NonEmptyVector
* scala> val nev = NonEmptyVector.of(1, 2, 3)
* scala> nev ++: NonEmptyVector.of(4, 5)
* res0: cats.data.NonEmptyVector[Int] = NonEmptyVector(1, 2, 3, 4, 5)
* }}}
*/
def ++:[AA >: A](other: NonEmptyVector[AA]): NonEmptyVector[AA] = other.concatNev(this)

/**
* Append another `Vector` to this, producing a new `NonEmptyVector`.
*/
Expand Down
Loading

0 comments on commit cd2e1f5

Please sign in to comment.