Skip to content
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

Issue 3141 #1

Open
wants to merge 89 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
3457276
Enhance EitherT and fix #2161: add MonadError.redeem/redeemWith
alexandru Apr 23, 2018
e3bd620
Added combineAllOption to Foldable
barambani Aug 10, 2018
94fcff1
Attempt
barambani Sep 30, 2018
7600623
Added separateFoldable
tkroman Mar 4, 2019
c703e70
format
tkroman Mar 4, 2019
23e8a28
scalafmt
tkroman Mar 4, 2019
dd02f8e
syntax
tkroman Mar 4, 2019
ebde934
syntax test
tkroman Mar 4, 2019
8ba46a3
syntax test
tkroman Mar 4, 2019
d7463af
syntax test
tkroman Mar 4, 2019
d9990ad
syntax in a separate class
tkroman Mar 4, 2019
e5372d0
NonEmptyChain.fromSeq should take scala.collection.Seq instead of sca…
gheine Mar 25, 2019
7f252c7
Merge branch 'master' into issue-2363
barambani May 8, 2019
7f8e044
prePR
barambani May 8, 2019
2c60919
Merge remote-tracking branch 'upstream/master'
gheine May 9, 2019
200d9c0
Merge branch 'master' into issue-2363
barambani Nov 8, 2019
2e4f67f
Merge branch 'master' into topic/nec-fromSeq
travisbrown Nov 8, 2019
82eebee
Fix bincompat
travisbrown Nov 8, 2019
654aae5
Added overrides for iterator, adapted tests, deprecated Stream
barambani Nov 8, 2019
64053b5
Removed tc iterator and changed with LazyList for 2.13 and Stream for
barambani Nov 9, 2019
427c7f5
Restored original iterator in tests, added iterable syntax and test
barambani Nov 9, 2019
38cbe68
Removed `override` non needed, refined tests
barambani Nov 9, 2019
f951eef
Implemented fold in terms of iterable
barambani Nov 9, 2019
2d835f1
Changed to Iterable
barambani Nov 11, 2019
a210efe
Update alternative.scala
tkroman Nov 12, 2019
f0b982c
Update alternative.scala
tkroman Nov 12, 2019
0f76a76
Merge branch 'master' of github.com:typelevel/cats into separateFoldable
tkroman Nov 12, 2019
2f42f4e
Revert non-redeem parts of 3457276881fd748143712e097df68d138feb60df
travisbrown Nov 13, 2019
69c5650
Merge branch 'master' into topic/add-redeem
travisbrown Nov 13, 2019
a8ca542
Move redeem to ApplicativeError
travisbrown Nov 13, 2019
1385170
Add redeem and redeemWith syntax methods
travisbrown Nov 13, 2019
9d92797
Add redeem and redeemWith syntax tests
travisbrown Nov 13, 2019
35e9b1f
Add parFoldMapA
nigredo-tori Nov 13, 2019
befb47a
Move adaptError
travisbrown Nov 13, 2019
bdc2b25
Move adaptError laws
travisbrown Nov 13, 2019
3b8ba69
Correct API docs
travisbrown Nov 13, 2019
6ba59df
Fix redeem API docs
travisbrown Nov 13, 2019
d5b96dd
Clean up following MR discussion
nigredo-tori Nov 14, 2019
0259244
Move ParallelFoldMapASyntax from AllSyntaxBinCompat to AllSyntax
nigredo-tori Nov 14, 2019
2ce81ea
#3141 [WIP] Implemented .foldA
Twizty Nov 14, 2019
ac9efdc
#3141 [WIP] Implemented .reduceA
Twizty Nov 14, 2019
6d28b9c
#3141 [WIP] Implemented .reduceMapA
Twizty Nov 14, 2019
e0a572f
Add ifA to Apply
travisbrown Nov 14, 2019
0655be3
Add sequenceFilter to TraverseFilter
travisbrown Nov 14, 2019
a11a61c
Add count to UnorderedFoldable
travisbrown Nov 14, 2019
155a663
Add fromOption and fromValidated to ApplicativeError
travisbrown Nov 14, 2019
7c43027
Add leftTraverse and leftSequence to Bitraverse
travisbrown Nov 14, 2019
d8e0089
Add @noop to avoid generating redundant syntax methods
travisbrown Nov 14, 2019
731bc13
Add foreverM, iterateForeverM, and untilDefinedM to FlatMap
travisbrown Nov 14, 2019
63b2d8b
Add findM to Foldable
travisbrown Nov 14, 2019
0ea4183
Add reduceMapK to Reducible
travisbrown Nov 14, 2019
762cb2c
Add collectFirstSomeM to Foldable
travisbrown Nov 14, 2019
30d556e
Add collectFold and collectFoldSome to Foldable
travisbrown Nov 14, 2019
20deedb
Fix doc test
travisbrown Nov 14, 2019
b689e54
Fix doc test
travisbrown Nov 14, 2019
5867e66
Move Foldable extension methods onto Foldable
travisbrown Nov 14, 2019
4402e0d
Add foldMapK to Foldable
travisbrown Nov 14, 2019
7b30d5b
Clean up redundant syntax methods
travisbrown Nov 14, 2019
a0e95be
fix link to moniodK and Applicative
stsatlantis Nov 14, 2019
8d67ec6
Merge pull request #2380 from barambani/issue-2363
travisbrown Nov 14, 2019
442a121
Merge pull request #3133 from travisbrown/topic/nec-fromSeq
travisbrown Nov 14, 2019
4af62d7
Merge pull request #2742 from tkroman/separateFoldable
travisbrown Nov 14, 2019
53a0f59
Merge pull request #3146 from travisbrown/topic/add-redeem
travisbrown Nov 14, 2019
bd82ff2
Merge pull request #3147 from nigredo-tori/parfoldmapa
travisbrown Nov 14, 2019
91ad29a
Merge branch 'master' into topic/move-adapt-error
travisbrown Nov 14, 2019
0a41922
Use adaptError from type class
travisbrown Nov 14, 2019
d01a0b5
Fix adaptError API doc tests
travisbrown Nov 14, 2019
a727fbf
Add adaptError and adaptErr syntax tests
travisbrown Nov 14, 2019
1d1b261
Merge pull request #3148 from travisbrown/topic/move-adapt-error
travisbrown Nov 14, 2019
c3eed57
Merge pull request #3151 from stsatlantis/patch-1
travisbrown Nov 15, 2019
12cfc54
Make 1.x deprecation targets package-private
travisbrown Nov 15, 2019
d52979c
Avoid deprecated / package-private concat in test
travisbrown Nov 15, 2019
93f70cd
Fix link to Monad and Comonad
XeeD Nov 15, 2019
03c4720
Merge pull request #3156 from XeeD/patch-1
travisbrown Nov 15, 2019
f914fb5
#3141 Refactored
Twizty Nov 15, 2019
aa36227
#3141 Added tests
Twizty Nov 15, 2019
ae5a3d7
#3141 Fixed 2.13
Twizty Nov 15, 2019
1ff4848
#3141 Added link to the issue at simulacrum
Twizty Nov 15, 2019
07f8d38
#3141 Fixed docs
Twizty Nov 15, 2019
4563806
Merge pull request #3154 from travisbrown/topic/1.x-deprecations
travisbrown Nov 15, 2019
291af38
Merge pull request #3152 from travisbrown/topic/type-class-methods
travisbrown Nov 15, 2019
8867e97
2.1.0-RC1 follow-up (#3157)
travisbrown Nov 16, 2019
971f380
Merge branch 'master' into issue3141
Twizty Nov 18, 2019
d59858a
#3141 Formatted
Twizty Nov 18, 2019
619b1b4
#3141 Refactored
Twizty Nov 18, 2019
c910cea
#3141 Changed .reduceMap signature
Twizty Nov 18, 2019
82c16e1
#3141 Removed noop on .reduceMapA
Twizty Nov 19, 2019
6eebfeb
#3141 Fixed docs
Twizty Nov 19, 2019
c63b8bc
#3141 Removed changes from reduceMapK
Twizty Nov 20, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ possible:
* Arya Irani
* Ash Pook
* Aλ
* Barnabás Oláh
* Ben Fradet
* Ben Hutchison
* Ben Kirwin
Expand Down Expand Up @@ -79,6 +80,7 @@ possible:
* Denis
* Derek Wickern
* Diego Esteban Alonso Blas
* Dmitry Polienko
* Donaldo Salas
* Earl St Sauver
* Edd Steel
Expand All @@ -104,10 +106,12 @@ possible:
* Gabriele Petronella
* Gagandeep Kalra
* Gavin Bisesi
* Georgi Krastev
* Giovanni Ruggiero
* Giulio De Luise
* Giuseppe Cannella
* Greg Pfeil
* Gregor Heine
* Guillaume Massé
* Hamed Nourhani
* Hamish Dickson
Expand Down Expand Up @@ -151,10 +155,12 @@ possible:
* Lars Hupel
* Leandro Bolivar
* Leif Battermann
* Lionel Parreaux
* Long Cao
* Luis Angel Vicente Sanchez
* Luis Sanchez
* Luka Jacobowitz
* Lukáš Voda
* Luke Wyman
* Madder
* Marc Siegel
Expand All @@ -169,11 +175,13 @@ possible:
* Matt Martin
* Matthias Lüneberg
* Max Worgan
* Maxim Davydov
* Merlin Göttlinger
* Michał Gutowski
* Michael Ledin
* Michael Pilquist
* Mike Curry
* Miklós Martin
* Miles Sabin
* Mirco Dotta
* nigredo-tori
Expand Down Expand Up @@ -210,6 +218,7 @@ possible:
* Rob Norris
* Rohan Shah
* Romain Ruetschi
* Roman Tkalenko
* Ross A. Baker
* rsekulski
* rsoeldner
Expand All @@ -228,6 +237,7 @@ possible:
* Stephen Carman
* Stephen Judkins
* Stephen Lazaro
* Steven Scott
* Suhas Gaddam
* sullis
* Sumedh Mungee
Expand Down
97 changes: 97 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,100 @@
## Version 2.1.0-RC1

_2019 November 15_

This release is currently only available for Scala 2.11 and Scala 2.12. It provides the same binary compatibility guarantees as Cats 2.0 (and is verified by MiMa to be fully binary-compatible with 2.0 itself).

### 2 source breaking changes

* [#3154](https://github.com/typelevel/cats/pull/3154) Make 1.x deprecation targets package-private by @travisbrown
* [#3099](https://github.com/typelevel/cats/pull/3099) Issue 3059: Move Parallel instances into instance packages for the type constructors they characterize by @barambani


### 3 bug fixes

* [#3126](https://github.com/typelevel/cats/pull/3126) Remove Order constraint from Hash instance for Map by @vasiliybondarenko
* [#3105](https://github.com/typelevel/cats/pull/3105) Issue 2701 - Ambiguous Eq instances for tuples by @barambani
* [#3100](https://github.com/typelevel/cats/pull/3100) Issue 2891 - Ambiguous Vector instances by @barambani


### 25 API / feature enhancements

* [#3152](https://github.com/typelevel/cats/pull/3152) "Move" type class syntax methods onto type classes by @travisbrown
* [#3149](https://github.com/typelevel/cats/pull/3149) Deprecate and make private syntax methods that are now on Either by @travisbrown
* [#3148](https://github.com/typelevel/cats/pull/3148) Move adaptError by @travisbrown
* [#3147](https://github.com/typelevel/cats/pull/3147) Add Parallel.parFoldMapA by @nigredo-tori
* [#3146](https://github.com/typelevel/cats/pull/3146) Add redeem and redeemWith by @travisbrown
* [#3144](https://github.com/typelevel/cats/pull/3144) Add Align for Stream by @travisbrown
* [#3136](https://github.com/typelevel/cats/pull/3136) Add benchmark for foldMapA by @travisbrown
* [#3135](https://github.com/typelevel/cats/pull/3135) Minor clean up. Removed duplication. by @barambani
* [#3133](https://github.com/typelevel/cats/pull/3133) Fix NonEmptyChain.fromSeq signature on 2.12 by @travisbrown
* [#3130](https://github.com/typelevel/cats/pull/3130) add foldMapA as an alternative to foldMapM that only requires an Applicative rather than a monad by @mberndt123
* [#3124](https://github.com/typelevel/cats/pull/3124) SemigroupK sum: F[A], F[B] => F[A Either B] by @pk044
* [#3122](https://github.com/typelevel/cats/pull/3122) Fix constraints and names for new Foldable methods by @travisbrown
* [#3103](https://github.com/typelevel/cats/pull/3103) Add TraverseFilter instance for Queue. by @takayahilton
* [#3088](https://github.com/typelevel/cats/pull/3088) #2947 Added bifold to Bifoldable typeclass by @Twizty
* [#3084](https://github.com/typelevel/cats/pull/3084) Add minimumBy/maximumBy/Option to Foldable by @joroKr21
* [#3076](https://github.com/typelevel/cats/pull/3076) Add Align typeclass by @LukaJCB
* [#3062](https://github.com/typelevel/cats/pull/3062) add unzip to Functor by @gagandeepkalra
* [#3058](https://github.com/typelevel/cats/pull/3058) Add `ifF` on Functor #3040 by @vasiliybondarenko
* [#3041](https://github.com/typelevel/cats/pull/3041) Add scala.util.control.TailCalls.TailRec instances by @johnynek
* [#3015](https://github.com/typelevel/cats/pull/3015) Use Foldable foldRight for Traverse and TraverseFilter. by @takayahilton
* [#2863](https://github.com/typelevel/cats/pull/2863) add attemptNarrow to ApplicativeErrorOps by @marcodippy
* [#2834](https://github.com/typelevel/cats/pull/2834) CommutativeMonoid[Option[A]] from CommutativeSemigroup by @valydia
* [#2772](https://github.com/typelevel/cats/pull/2772) Add foldRightDefer to Foldable by @denisrosca
* [#2742](https://github.com/typelevel/cats/pull/2742) Added separateFoldable by @tkroman
* [#2380](https://github.com/typelevel/cats/pull/2380) Add combineAllOption to Foldable by @barambani


### 12 documentation improvements

* [#3156](https://github.com/typelevel/cats/pull/3156) Fix link to Monad and Comonad by @XeeD
* [#3151](https://github.com/typelevel/cats/pull/3151) fix link to moniodK and Applicative by @stsatlantis
* [#3104](https://github.com/typelevel/cats/pull/3104) Update faq.md repl documentation by @psilospore
* [#3081](https://github.com/typelevel/cats/pull/3081) Correct some mistakes in Comonad documentatoin by @justinhj
* [#3073](https://github.com/typelevel/cats/pull/3073) add more doctest to WriterT by @hamednourhani
* [#3072](https://github.com/typelevel/cats/pull/3072) Mention additional dependencies in lawtesting docs by @miklos-martin
* [#3071](https://github.com/typelevel/cats/pull/3071) Update Semigroup docs for Map by @codingismy11to7
* [#3065](https://github.com/typelevel/cats/pull/3065) Link to relevant Const doc from doc of Traverse by @LPTK
* [#3063](https://github.com/typelevel/cats/pull/3063) add more doctest to Ior by @hamednourhani
* [#3061](https://github.com/typelevel/cats/pull/3061) Validated doctest by @hamednourhani
* [#3054](https://github.com/typelevel/cats/pull/3054) add more doctest to EitherT by @hamednourhani
* [#3049](https://github.com/typelevel/cats/pull/3049) minor update to the doc to include cats-testkit-scalatest by @kailuowang


### 29 build improvements

* [#3142](https://github.com/typelevel/cats/pull/3142) Backport MiMa config and dependency updates for 2.11 by @travisbrown
* [#3139](https://github.com/typelevel/cats/pull/3139) Update 2.11 branch build by @travisbrown
* [#3129](https://github.com/typelevel/cats/pull/3129) Check bincompat on stuff we should be checking bincompat for by @travisbrown
* [#3125](https://github.com/typelevel/cats/pull/3125) Fix order of @deprecated arguments by @travisbrown
* [#3120](https://github.com/typelevel/cats/pull/3120) Update sbt-scalafmt to 2.2.1 by @scala-steward
* [#3118](https://github.com/typelevel/cats/pull/3118) Update sbt-scalafmt to 2.2.0 by @scala-steward
* [#3115](https://github.com/typelevel/cats/pull/3115) Update sbt-release to 1.0.12 by @scala-steward
* [#3114](https://github.com/typelevel/cats/pull/3114) Update sbt to 1.3.3 by @scala-steward
* [#3110](https://github.com/typelevel/cats/pull/3110) Update sbt-scalafmt to 2.0.7 by @scala-steward
* [#3106](https://github.com/typelevel/cats/pull/3106) ci: Enable 2.13 build for scalajs and linting in travis by @DieBauer
* [#3102](https://github.com/typelevel/cats/pull/3102) Use new group ID for simulacrum by @travisbrown
* [#3101](https://github.com/typelevel/cats/pull/3101) update ScalaTest by @larsrh
* [#3096](https://github.com/typelevel/cats/pull/3096) Enable coverage and docs by @DieBauer
* [#3095](https://github.com/typelevel/cats/pull/3095) Update sbt-microsites to 0.9.7 by @scala-steward
* [#3094](https://github.com/typelevel/cats/pull/3094) Update tut-plugin to 0.6.13 by @scala-steward
* [#3092](https://github.com/typelevel/cats/pull/3092) Update scalafmt-core to 2.1.0 by @scala-steward
* [#3091](https://github.com/typelevel/cats/pull/3091) Update sbt-sonatype to 3.8 by @scala-steward
* [#3090](https://github.com/typelevel/cats/pull/3090) Update sbt-scalafmt to 2.0.6 by @scala-steward
* [#3089](https://github.com/typelevel/cats/pull/3089) Update scalacheck to 1.14.2 by @scala-steward
* [#3086](https://github.com/typelevel/cats/pull/3086) Update simulacrum to 1.0.0 by @scala-steward
* [#3085](https://github.com/typelevel/cats/pull/3085) Update sbt-microsites to 0.9.6 by @scala-steward
* [#3079](https://github.com/typelevel/cats/pull/3079) update to sbt 1.3.x, uses coursier by default by @larsrh
* [#3070](https://github.com/typelevel/cats/pull/3070) Update sbt-scalajs, scalajs-compiler to 0.6.29 by @scala-steward
* [#3066](https://github.com/typelevel/cats/pull/3066) Update sbt-scalafmt to 2.0.5 by @scala-steward
* [#3064](https://github.com/typelevel/cats/pull/3064) Update sbt-pgp to 2.0.1-M3 by @scala-steward
* [#3056](https://github.com/typelevel/cats/pull/3056) Update sbt-sonatype to 3.7 by @scala-steward
* [#3052](https://github.com/typelevel/cats/pull/3052) Create a Scala 2.11 branch by @kailuowang
* [#3051](https://github.com/typelevel/cats/pull/3051) Drops Scala 2.11 support on master by @kailuowang
* [#3030](https://github.com/typelevel/cats/pull/3030) Update sbt-sonatype to 3.6 by @scala-steward


## Version 2.0.0

> 2019 September 9
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

### ![#f03c15](https://placehold.it/15/f03c15/000000?text=+) Community Announcements ![#f03c15](https://placehold.it/15/f03c15/000000?text=+)
* **Nov 15 2019** [Cats 2.1.0-RC1 is released](https://github.com/typelevel/cats/releases/tag/v2.1.0-RC1)
* **Sep 9 2019** [Cats 2.0.0 is released](https://github.com/typelevel/cats/releases/tag/v2.0.0)
* **Sep 7 2019** [Cats 2.0.0-RC3 is released](https://github.com/typelevel/cats/releases/tag/v2.0.0-RC3)
* **Aug 26 2019** [Cats 2.0.0-RC2 is released](https://github.com/typelevel/cats/releases/tag/v2.0.0-RC2)
Expand Down
11 changes: 11 additions & 0 deletions core/src/main/scala-2.12/cats/compat/FoldableCompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package cats
package compat

private[cats] object FoldableCompat {

def toIterable[F[_], A](fa: F[A])(F: Foldable[F]): Iterable[A] =
F.foldRight[A, Stream[A]](fa, Eval.now(Stream.empty)) { (a, eb) =>
eb.map(Stream.cons(a, _))
}
.value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package cats.data

private[data] trait ScalaVersionSpecificNonEmptyChainImpl {
def fromSeq[A](as: scala.collection.Seq[A]): Option[NonEmptyChain[A]] =
if (as.nonEmpty) Option(NonEmptyChainImpl.create(Chain.fromSeq(as))) else None
}
2 changes: 2 additions & 0 deletions core/src/main/scala-2.12/cats/instances/stream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ trait StreamInstances extends cats.kernel.instances.StreamInstances {

override def toList[A](fa: Stream[A]): List[A] = fa.toList

override def toIterable[A](fa: Stream[A]): Iterable[A] = fa

override def reduceLeftOption[A](fa: Stream[A])(f: (A, A) => A): Option[A] =
fa.reduceLeftOption(f)

Expand Down
11 changes: 11 additions & 0 deletions core/src/main/scala-2.13+/cats/compat/FoldableCompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package cats
package compat

private[cats] object FoldableCompat {

def toIterable[F[_], A](fa: F[A])(F: Foldable[F]): Iterable[A] =
F.foldRight[A, LazyList[A]](fa, Eval.now(LazyList.empty)) { (a, eb) =>
eb.map(LazyList.cons(a, _))
}
.value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package cats.data

private[data] trait ScalaVersionSpecificNonEmptyChainImpl
2 changes: 2 additions & 0 deletions core/src/main/scala-2.13+/cats/instances/lazyList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ trait LazyListInstances extends cats.kernel.instances.LazyListInstances {

override def toList[A](fa: LazyList[A]): List[A] = fa.toList

override def toIterable[A](fa: LazyList[A]): Iterable[A] = fa

override def reduceLeftOption[A](fa: LazyList[A])(f: (A, A) => A): Option[A] =
fa.reduceLeftOption(f)

Expand Down
2 changes: 2 additions & 0 deletions core/src/main/scala-2.13+/cats/instances/stream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ trait StreamInstances extends cats.kernel.instances.StreamInstances {

override def toList[A](fa: Stream[A]): List[A] = fa.toList

override def toIterable[A](fa: Stream[A]): Iterable[A] = fa

override def reduceLeftOption[A](fa: Stream[A])(f: (A, A) => A): Option[A] =
fa.reduceLeftOption(f)

Expand Down
24 changes: 24 additions & 0 deletions core/src/main/scala/cats/Alternative.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@ import simulacrum.typeclass
(as, bs)
}

/**
* Separate the inner foldable values into the "lefts" and "rights".
* A variant of [[separate]] that is specialized
* for Fs that have Foldable instances
* which allows for a single-pass implementation
* (as opposed to {{{separate}}} which is 2-pass).
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> val l: List[Either[String, Int]] = List(Right(1), Left("error"))
* scala> Alternative[List].separate(l)
* res0: (List[String], List[Int]) = (List(error),List(1))
* }}}
*/
def separateFoldable[G[_, _], A, B](fgab: F[G[A, B]])(implicit G: Bifoldable[G], FF: Foldable[F]): (F[A], F[B]) =
FF.foldLeft(fgab, (empty[A], empty[B])) {
case (mamb, gab) =>
G.bifoldLeft(gab, mamb)(
(t, a) => (combineK(t._1, pure(a)), t._2),
(t, b) => (t._1, combineK(t._2, pure(b)))
)
}

/**
* Return ().pure[F] if `condition` is true, `empty` otherwise
*
Expand Down
104 changes: 103 additions & 1 deletion core/src/main/scala/cats/ApplicativeError.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats

import cats.data.EitherT
import cats.data.{EitherT, Validated}
import cats.data.Validated.{Invalid, Valid}

import scala.reflect.ClassTag
import scala.util.{Failure, Success, Try}
Expand Down Expand Up @@ -103,6 +104,65 @@ trait ApplicativeError[F[_], E] extends Applicative[F] {
def recoverWith[A](fa: F[A])(pf: PartialFunction[E, F[A]]): F[A] =
handleErrorWith(fa)(e => pf.applyOrElse(e, raiseError))

/**
* Transform certain errors using `pf` and rethrow them.
* Non matching errors and successful values are not affected by this function.
*
* Example:
* {{{
* scala> import cats._, implicits._
*
* scala> def pf: PartialFunction[String, String] = { case "error" => "ERROR" }
*
* scala> ApplicativeError[Either[String, *], String].adaptError("error".asLeft[Int])(pf)
* res0: Either[String,Int] = Left(ERROR)
*
* scala> ApplicativeError[Either[String, *], String].adaptError("err".asLeft[Int])(pf)
* res1: Either[String,Int] = Left(err)
*
* scala> ApplicativeError[Either[String, *], String].adaptError(1.asRight[String])(pf)
* res2: Either[String,Int] = Right(1)
* }}}
*
* The same function is available in `ApplicativeErrorOps` as `adaptErr` - it cannot have the same
* name because this would result in ambiguous implicits due to `adaptError`
* having originally been included in the `MonadError` API and syntax.
*/
def adaptError[A](fa: F[A])(pf: PartialFunction[E, E]): F[A] =
recoverWith(fa)(pf.andThen(raiseError[A] _))

/**
* Returns a new value that transforms the result of the source,
* given the `recover` or `map` functions, which get executed depending
* on whether the result is successful or if it ends in error.
*
* This is an optimization on usage of [[attempt]] and [[map]],
* this equivalence being available:
*
* {{{
* fa.redeem(fe, fs) <-> fa.attempt.map(_.fold(fe, fs))
* }}}
*
* Usage of `redeem` subsumes [[handleError]] because:
*
* {{{
* fa.redeem(fe, id) <-> fa.handleError(fe)
* }}}
*
* Implementations are free to override it in order to optimize
* error recovery.
*
* @see [[MonadError.redeemWith]], [[attempt]] and [[handleError]]
*
* @param fa is the source whose result is going to get transformed
* @param recover is the function that gets called to recover the source
* in case of error
* @param map is the function that gets to transform the source
* in case of success
*/
def redeem[A, B](fa: F[A])(recover: E => B, f: A => B): F[B] =
handleError(map(fa)(f))(recover)

/**
* Execute a callback on certain errors, then rethrow them.
* Any non matching error is rethrown as well.
Expand Down Expand Up @@ -186,6 +246,48 @@ trait ApplicativeError[F[_], E] extends Applicative[F] {
case Left(e) => raiseError(e)
}

/**
* Convert from scala.Option
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> import cats.ApplicativeError
* scala> val F = ApplicativeError[Either[String, *], String]
*
* scala> F.fromOption(Some(1), "Empty")
* res0: scala.Either[String, Int] = Right(1)
*
* scala> F.fromOption(Option.empty[Int], "Empty")
* res1: scala.Either[String, Int] = Left(Empty)
* }}}
*/
def fromOption[A](oa: Option[A], ifEmpty: => E): F[A] =
oa match {
case Some(a) => pure(a)
case None => raiseError(ifEmpty)
}

/**
* Convert from cats.data.Validated
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> import cats.ApplicativeError
*
* scala> ApplicativeError[Option, Unit].fromValidated(1.valid[Unit])
* res0: scala.Option[Int] = Some(1)
*
* scala> ApplicativeError[Option, Unit].fromValidated(().invalid[Int])
* res1: scala.Option[Int] = None
* }}}
*/
def fromValidated[A](x: Validated[E, A]): F[A] =
x match {
case Invalid(e) => raiseError(e)
case Valid(a) => pure(a)
}
}

object ApplicativeError {
Expand Down
Loading