Skip to content

Commit

Permalink
Merge branch 'master' into filter-classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Luka Jacobowitz authored and Luka Jacobowitz committed Sep 2, 2018
2 parents bf07dd3 + 6ac776c commit 716d701
Show file tree
Hide file tree
Showing 26 changed files with 535 additions and 109 deletions.
28 changes: 27 additions & 1 deletion AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ possible:
* Allan Timothy Leong
* Alonso Dominguez
* Amir Mohammad Saied
* Amitay Horwitz
* Andrea Fiore
* Andrea McAts
* Andrew Jones
Expand All @@ -46,6 +47,7 @@ possible:
* Bobby Rauchenberg
* Brendan McAdams
* Brian McKenna
* Brian P. Holt
* Bryan Tan
* Cary Robbins
* Chris Birchall
Expand All @@ -55,7 +57,9 @@ possible:
* Colt Frederickson
* Connie Chen
* Csongor Kiss
* dadepo
* Dale Wijnand
* Daniel Karch
* Daniel Spiewak
* Daniel Urban
* Daniela Sfregola
Expand All @@ -64,14 +68,17 @@ possible:
* David Allsopp
* David Gregory
* David R. Bild
* Dayyan Lord
* Denis Mikhaylov
* Denis Rosca
* Denis
* Derek Wickern
* Diego Esteban Alonso Blas
* Donaldo Salas
* Earl St Sauver
* Edd Steel
* Eric Torreborre
* ericaovo
* Erik LaBianca
* Erik Osheim
* Eugene Burmako
Expand All @@ -80,12 +87,16 @@ possible:
* Fabian Gutierrez
* Fabian Schmitthenner
* Fabio Labella
* fantayeneh
* Feynman Liang
* Filipe Oliveira
* Filippo Mariotti
* Francisco Bermejo
* Francisco Canedo
* Francois Armand
* Frank S. Thomas
* Gabriele Petronella
* Gavin Bisesi
* Giovanni Ruggiero
* Giulio De Luise
* Greg Pfeil
Expand All @@ -103,6 +114,8 @@ possible:
* Jan-Hendrik Zab
* Jean-Rémi Desjardins
* Jens
* Jens Grassel
* Jimin Hsieh
* Jisoo Park
* João Ferreira
* John Sullivan
Expand All @@ -112,10 +125,12 @@ possible:
* Josh Marcus
* Juan Pedro Moreno
* Juan Valencia
* Jules Ivanic
* Julien Richard-Foy
* Julien Truffaut
* Jun Tomioka
* Kailuo Wang
* Keir Lawson
* kellen
* Kenji Yoshida
* Lars Hupel
Expand All @@ -130,8 +145,10 @@ possible:
* Marc Siegel
* Marcin Rzeźnicki
* Marco Battaglia
* Mariot Chauvin
* Mark de Jong
* Markus Hauck
* Martijn Hoekstra
* mathhun
* Matt Martin
* Matthias Lüneberg
Expand All @@ -142,6 +159,7 @@ possible:
* Mike Curry
* Miles Sabin
* nigredo-tori
* Nikolay Maksimenko
* n4to4
* Olivier Blanvillain
* Olli Helenius
Expand All @@ -154,12 +172,14 @@ possible:
* Paulo "JCranky" Siqueira
* Pavel Chlupacek
* Pavkin Vladimir
* Paweł Lipski
* Pepe García
* Pere Villega
* Peter Neyens
* Peter Perhac
* phderome
* Philip Wills
* Piotr Gawryś
* Rafa Paradela
* Raúl Raja Martínez
* RawToast
Expand All @@ -171,8 +191,10 @@ possible:
* Rohan Shah
* Romain Ruetschi
* Ross A. Baker
* rsekulski
* rsoeldner
* Rüdiger Klaehn
* Rutvik Patel
* Ryan Case
* Sam Ritchie
* Sarunas Valaskevicius
Expand All @@ -181,10 +203,10 @@ possible:
* Shunsuke Otani
* Simeon H. K. Fitch
* Sinisa Louc
* Song Kun
* Stephen Carman
* Stephen Judkins
* Stephen Lazaro
* Stew O'Connor
* Suhas Gaddam
* sullis
* Sumedh Mungee
Expand All @@ -193,6 +215,7 @@ possible:
* Tom Switzer
* Tomas Mikula
* Tongfei Chen
* Torsten Schmits
* Travis Brown
* Trond Bjerkestrand
* Tya
Expand All @@ -210,7 +233,10 @@ possible:
* Yilin Wei
* Zach Abbott
* zainab-ali
* Zelenya
* zhen
* Ziyang Liu
* λoλcat

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
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,14 @@ By sharing the same set of type classes, instances and data types provided by Ca

#### General purpose libraries to support pure functional programming

* [Dogs](https://github.com/stew/dogs): pure functional collections and data structures
* [cats-par](https://github.com/ChristopherDavenport/cats-par): Abstract type member Parallel instances
* [cats-scalacheck](https://github.com/ChristopherDavenport/cats-scalacheck): cats typeclass instances for scalacheck
* [cats-time](https://github.com/ChristopherDavenport/cats-time): cats typeclass instances for java time
* [droste](https://github.com/andyscott/droste): recursion schemes for Cats
* [Dsl.scala](https://github.com/ThoughtWorksInc/Dsl.scala): The `!`-notation for creating Cats monadic expressions
* [eff](https://github.com/atnos-org/eff): functional effects and effect handlers (alternative to monad transformers)
* [Freestyle](https://github.com/frees-io/freestyle): pure functional framework for Free and Tagless Final apps & libs
* [fuuid](https://github.com/ChristopherDavenport/fuuid): functional uuid's
* [iota](https://github.com/frees-io/iota): Fast [co]product types with a clean syntax
* [Monocle](https://github.com/julien-truffaut/Monocle): an optics library for Scala (and Scala.js) strongly inspired by Haskell Lens.
* [newts](https://github.com/julien-truffaut/newts): Defines newtypes compatible with Cats type classes
Expand All @@ -93,6 +96,7 @@ By sharing the same set of type classes, instances and data types provided by Ca
* [atto](https://github.com/tpolecat/atto): friendly little text parsers
* [circe](https://github.com/circe/circe): pure functional JSON library
* [Ciris](https://github.com/vlovgr/ciris): Lightweight, extensible, and validated configuration loading in Scala
* [cormorant](https://github.com/ChristopherDavenport/cormorant): CSV handling library for FP
* [decline](https://github.com/bkirwi/decline): A composable command-line parser
* [doobie](https://github.com/tpolecat/doobie): a pure functional JDBC layer for Scala
* [fastparse-cats](https://github.com/johnynek/fastparse-cats): cats Monad and Alternative instances for [fastparse](https://github.com/lihaoyi/fastparse)
Expand All @@ -106,6 +110,8 @@ By sharing the same set of type classes, instances and data types provided by Ca
* [http4s](https://github.com/http4s/http4s): A minimal, idiomatic Scala interface for HTTP
* [monadic-html](https://github.com/OlivierBlanvillain/monadic-html): Tiny DOM binding library for Scala.js
* [Monix](https://github.com/monix/monix): high-performance library for composing asynchronous and event-based programs
* [linebacker](https://github.com/ChristopherDavenport/linebacker): functional thread pool management
* [log4cats](https://github.com/ChristopherDavenport/log4cats): functional logging
* [pureconfig](https://github.com/pureconfig/pureconfig): A boilerplate-free library for loading configuration files
* [rainier](https://github.com/stripe/rainier): Bayesian inference in Scala
* [scanamo](https://github.com/guardian/scanamo): simpler DynamoDB access for Scala
Expand Down Expand Up @@ -190,6 +196,7 @@ Here's a (non-exhaustive) list of companies that use Cats in production. Don't s
- [AutoScout24](https://www.autoscout24.com)
- [Avast](https://avast.com)
- [Banno Group inside of Jack Henry & Associates](https://banno.com/)
- [Basefarm](https://basefarm.com/)
- [buildo](https://buildo.io)
- [Codacy](https://www.codacy.com/)
- [Codecentric](https://codecentric.de)
Expand All @@ -214,14 +221,17 @@ Here's a (non-exhaustive) list of companies that use Cats in production. Don't s
- [Scalac](https://scalac.io)
- [Scala Center](https://scala.epfl.ch)
- [Snowplow Analytics](https://snowplowanalytics.com/)
- [Spiceworks](https://www.spiceworks.com/)
- [Spotahome](https://spotahome.com)
- [Spotify](https://www.spotify.com)
- [SpringerNature](https://www.springernature.com)
- [Stripe](https://stripe.com)
- [Tecsisa](https://www.tecsisa.com)
- [Teikametrics](http://teikametrics.com)
- [The Guardian](https//www.theguardian.com)
- [Underscore Consulting](https://underscore.io/)
- [Wegtam GmbH](https://www.wegtam.com)
- [WeWork](https://www.wework.com)
- [Wix.com](https://www.wix.com)
- [Zalando](https://zalando.com)
- [47 Degrees](https://www.47deg.com)
Expand All @@ -238,7 +248,6 @@ The current maintainers (people who can merge pull requests) are:
* [LukaJCB](https://github.com/LukaJCB) Luka Jacobowitz
* [peterneyens](https://github.com/peterneyens) Peter Neyens
* [tpolecat](https://github.com/tpolecat) Rob Norris
* [stew](https://github.com/stew) Mike O'Connor
* [non](https://github.com/non) Erik Osheim
* [mpilquist](https://github.com/mpilquist) Michael Pilquist
* [milessabin](https://github.com/milessabin) Miles Sabin
Expand Down
5 changes: 0 additions & 5 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -556,11 +556,6 @@ lazy val publishSettings = Seq(
<name>Rob Norris</name>
<url>https://github.com/tpolecat/</url>
</developer>
<developer>
<id>stew</id>
<name>Mike O'Connor</name>
<url>https://github.com/stew/</url>
</developer>
<developer>
<id>non</id>
<name>Erik Osheim</name>
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/scala/cats/Foldable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -601,11 +601,11 @@ object Foldable {
* It could be made a value class after
* https://github.com/scala/bug/issues/9600 is resolved.
*/
private sealed abstract class Source[+A] {
private[cats] sealed abstract class Source[+A] {
def uncons: Option[(A, Eval[Source[A]])]
}

private object Source {
private[cats] object Source {
val Empty: Source[Nothing] = new Source[Nothing] {
def uncons = None
}
Expand Down
47 changes: 47 additions & 0 deletions core/src/main/scala/cats/FunctorFilter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,61 @@ import simulacrum.typeclass
trait FunctorFilter[F[_]] extends Serializable {
def functor: Functor[F]

/**
* A combined `map` and `filter`. Filtering is handled via `Option`
* instead of `Boolean` such that the output type `B` can be different than
* the input type `A`.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> val m: Map[Int, String] = Map(1 -> "one", 3 -> "three")
* scala> val l: List[Int] = List(1, 2, 3, 4)
* scala> def asString(i: Int): Option[String] = m.get(i)
* scala> l.mapFilter(i => m.get(i))
* res0: List[String] = List(one, three)
* }}}
*/
def mapFilter[A, B](fa: F[A])(f: A => Option[B]): F[B]

/**
* Similar to [[mapFilter]] but uses a partial function instead of a function
* that returns an `Option`.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> val l: List[Int] = List(1, 2, 3, 4)
* scala> FunctorFilter[List].collect(l){
* | case 1 => "one"
* | case 3 => "three"
* | }
* res0: List[String] = List(one, three)
* }}}
*/
def collect[A, B](fa: F[A])(f: PartialFunction[A, B]): F[B] =
mapFilter(fa)(f.lift)

/**
* "Flatten" out a structure by collapsing `Option`s.
* Equivalent to using `mapFilter` with `identity`.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> val l: List[Option[Int]] = List(Some(1), None, Some(3), None)
* scala> l.flattenOption
* res0: List[Int] = List(1, 3)
* }}}
*/
def flattenOption[A](fa: F[Option[A]]): F[A] =
mapFilter(fa)(identity)

/**
* Apply a filter to a structure such that the output structure contains all
* `A` elements in the input structure that satisfy the predicate `f` but none
* that don't.
*/
def filter[A](fa: F[A])(f: A => Boolean): F[A] =
mapFilter(fa)(a => if (f(a)) Some(a) else None)
}
26 changes: 26 additions & 0 deletions core/src/main/scala/cats/Semigroupal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,32 @@ import simulacrum.typeclass
* [[Semigroupal]] and [[Functor]] to illustrate this.
*/
@typeclass trait Semigroupal[F[_]] {

/**
* Combine an `F[A]` and an `F[B]` into an `F[(A, B)]` that maintains the effects of both `fa` and `fb`.
*
* Example:
* {{{
* scala> import cats.implicits._
*
* scala> val noneInt: Option[Int] = None
* scala> val some3: Option[Int] = Some(3)
* scala> val noneString: Option[String] = None
* scala> val someFoo: Option[String] = Some("foo")
*
* scala> Semigroupal[Option].product(noneInt, noneString)
* res0: Option[(Int, String)] = None
*
* scala> Semigroupal[Option].product(noneInt, someFoo)
* res1: Option[(Int, String)] = None
*
* scala> Semigroupal[Option].product(some3, noneString)
* res2: Option[(Int, String)] = None
*
* scala> Semigroupal[Option].product(some3, someFoo)
* res3: Option[(Int, String)] = Some((3,foo))
* }}}
*/
def product[A, B](fa: F[A], fb: F[B]): F[(A, B)]
}

Expand Down
36 changes: 36 additions & 0 deletions core/src/main/scala/cats/TraverseFilter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,44 @@ trait TraverseFilter[F[_]] extends FunctorFilter[F] {

final override def functor: Functor[F] = traverse

/**
* A combined [[traverse]] and [[filter]]. Filtering is handled via `Option`
* instead of `Boolean` such that the output type `B` can be different than
* the input type `A`.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> val m: Map[Int, String] = Map(1 -> "one", 3 -> "three")
* scala> val l: List[Int] = List(1, 2, 3, 4)
* scala> def asString(i: Int): Eval[Option[String]] = Now(m.get(i))
* scala> val result: Eval[List[String]] = l.traverseFilter(asString)
* scala> result.value
* res0: List[String] = List(one, three)
* }}}
*/
def traverseFilter[G[_], A, B](fa: F[A])(f: A => G[Option[B]])(implicit G: Applicative[G]): G[F[B]]

/**
*
* Filter values inside a `G` context.
*
* This is a generalized version of Haskell's [[http://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Monad.html#v:filterM filterM]].
* [[http://stackoverflow.com/questions/28872396/haskells-filterm-with-filterm-x-true-false-1-2-3 This StackOverflow question]] about `filterM` may be helpful in understanding how it behaves.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> val l: List[Int] = List(1, 2, 3, 4)
* scala> def odd(i: Int): Eval[Boolean] = Now(i % 2 == 1)
* scala> val res: Eval[List[Int]] = l.filterA(odd)
* scala> res.value
* res0: List[Int] = List(1, 3)
*
* scala> List(1, 2, 3).filterA(_ => List(true, false))
* res1: List[List[Int]] = List(List(1, 2, 3), List(1, 2), List(1, 3), List(1), List(2, 3), List(2), List(3), List())
* }}}
*/
def filterA[G[_], A](fa: F[A])(f: A => G[Boolean])(implicit G: Applicative[G]): G[F[A]] =
traverseFilter(fa)(a => G.map(f(a))(if (_) Some(a) else None))

Expand Down
Loading

0 comments on commit 716d701

Please sign in to comment.