cats.data.WriterT.scala Maven / Gradle / Ivy
The newest version!
package cats
package data
import cats.Foldable
import cats.kernel.CommutativeMonoid
import cats.syntax.semigroup._
final case class WriterT[F[_], L, V](run: F[(L, V)]) {
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val writer = WriterT.liftF[Option, List[String], Int](Some(123))
* scala> writer.tell(List("a","b","c")).tell(List("d","e","f"))
* res0: WriterT[Option, List[String], Int] = WriterT(Some((List(a, b, c, d, e, f),123)))
* }}}
*/
def tell(l: L)(implicit functorF: Functor[F], semigroupL: Semigroup[L]): WriterT[F, L, V] =
mapWritten(_ |+| l)
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val writer: WriterT[Option, List[String], Int] = WriterT.liftF(Some(123))
* scala> writer.tell(List("a","b","c")).written.getOrElse(Nil)
* res0: List[String] = List(a, b, c)
* }}}
*/
def written(implicit functorF: Functor[F]): F[L] =
functorF.map(run)(_._1)
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val writer: WriterT[Option, List[String], Int] = WriterT.liftF(Some(123))
* scala> val wt: WriterT[Option, List[String], Int] = writer.tell(List("error"))
* res0: WriterT[Option, List[String], Int] = WriterT(Some((List(error),123)))
*
* scala> wt.value
* res1: Option[Int] = Some(123)
* }}}
*/
def value(implicit functorF: Functor[F]): F[V] =
functorF.map(run)(_._2)
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val writer: WriterT[Option, String, Int] = WriterT.liftF(Some(123))
* scala> val wt: WriterT[Option, String, Int] = writer.tell("error").tell(" log")
* res0: WriterT[Option, String, Int] = WriterT(Some((error log,123)))
*
* scala> wt.listen
* res1: WriterT[Option, String, (Int,String)] = WriterT(Some((error log,(123,error log))))
* }}}
*/
def listen(implicit F: Functor[F]): WriterT[F, L, (V, L)] =
WriterT(F.map(run) {
case (l, v) => (l, (v, l))
})
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val writer: WriterT[Option, String, Int] = WriterT.liftF(Some(123))
* scala> val wt: WriterT[Option, String, Int] = writer.tell("error")
* res0: WriterT[Option, String, Int] = WriterT(Some((error,123)))
*
* scala> val func = WriterT.liftF[Option, String, Int => List[Int]](Some(i => List(i)))
* scala> val func2 = func.tell("log")
*
* scala> wt.ap(func2)
* res1: WriterT[Option, String, List[Int]] = WriterT(Some((logerror,List(123))))
* }}}
*/
def ap[Z](f: WriterT[F, L, V => Z])(implicit F: Apply[F], L: Semigroup[L]): WriterT[F, L, Z] =
WriterT(F.map2(f.run, run) {
case ((l1, fvz), (l2, v)) => (L.combine(l1, l2), fvz(v))
})
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val wr1: WriterT[Option, String, Int] = WriterT.liftF(None)
* scala> val wr2 = wr1.tell("error")
* res0: WriterT[Option, String, Int] = WriterT(None)
*
* scala> wr2.map(_ * 2)
* res1: WriterT[Option, String, Int] = WriterT(None)
*
* scala> val wr3: WriterT[Option, String, Int] = WriterT.liftF(Some(456))
* scala> val wr4 = wr3.tell("error")
* scala> wr4.map(_ * 2)
* res2: WriterT[Option, String, Int] = WriterT(Some((error,912)))
* }}}
*/
def map[Z](fn: V => Z)(implicit functorF: Functor[F]): WriterT[F, L, Z] =
WriterT {
functorF.map(run) { z =>
(z._1, fn(z._2))
}
}
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val wr1: WriterT[Option, String, Int] = WriterT.liftF(Some(123))
* scala> val wr2 = wr1.tell("log...")
* scala> wr2.imap(_ * 2)(_ / 2)
* res0: WriterT[Option, String, Int] = WriterT(Some((log...,246)))
* }}}
*/
def imap[Z](f: V => Z)(g: Z => V)(implicit F: Invariant[F]): WriterT[F, L, Z] =
WriterT {
F.imap(run)(z => (z._1, f(z._2)))(z => (z._1, g(z._2)))
}
/**
* Modify the context `F` using transformation `f`.
*
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.arrow.FunctionK
* scala> import cats.implicits._
*
* scala> val optionWriter = WriterT.liftF[Option, String, Int](Some(123)).tell("log")
* res0: WriterT[Option, String, Int](Some((log,123)))
*
* scala> def toList[A](option: Option[A]): List[A] = option.toList
* scala> val listWriter = optionWriter.mapK(FunctionK.lift(toList _))
* res1: WriterT[List, String, Int](List((log,123)))
* }}}
*/
def mapK[G[_]](f: F ~> G): WriterT[G, L, V] =
WriterT[G, L, V](f(run))
def contramap[Z](fn: Z => V)(implicit F: Contravariant[F]): WriterT[F, L, Z] =
WriterT {
F.contramap(run) { z =>
(z._1, fn(z._2))
}
}
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val wr1 = WriterT.liftF[Option, String, Int](Some(123)).tell("error")
* res0: WriterT[Option, String, Int] = WriterT(Some(error,123))
* scala> val func = (i:Int) => WriterT.liftF[Option, String, Int](Some(i * 2)).tell(i.show)
*
* scala> wr1.flatMap(func)
* res1: WriterT[Option, String, Int] = WriterT(Some((error123,246)))
* }}}
*/
def flatMap[U](f: V => WriterT[F, L, U])(implicit flatMapF: FlatMap[F], semigroupL: Semigroup[L]): WriterT[F, L, U] =
WriterT {
flatMapF.flatMap(run) { lv =>
flatMapF.map(f(lv._2).run) { lv2 =>
(semigroupL.combine(lv._1, lv2._1), lv2._2)
}
}
}
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val wr1 = WriterT.liftF[Option, String, Int](Some(123)).tell("quack")
* res0: WriterT[Option, String, Int] = WriterT(Some(quack,123))
*
* scala> wr1.mapBoth((s,i) => (s + " " + s, i * 2))
* res1: WriterT[Option, String, Int] = WriterT(Some((quack quack,246)))
* }}}
*/
def mapBoth[M, U](f: (L, V) => (M, U))(implicit functorF: Functor[F]): WriterT[F, M, U] =
WriterT { functorF.map(run)(f.tupled) }
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val wr1 = WriterT.liftF[Option, String, Int](Some(123)).tell("456")
* res0: WriterT[Option, String, Int] = WriterT(Some(456,123))
*
* scala> wr1.bimap(_.toInt, _.show)
* res1: WriterT[Option, Int, String] = WriterT(Some((456,123)))
* }}}
*/
def bimap[M, U](f: L => M, g: V => U)(implicit functorF: Functor[F]): WriterT[F, M, U] =
mapBoth((l, v) => (f(l), g(v)))
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(246)).tell("error")
* res0: WriterT[Option, String, Int] = WriterT(Some((error,246)))
*
* scala> writer.mapWritten(i => List(i))
* res1: WriterT[Option, List[String], Int] = WriterT(Some((List(error),246)))
* }}}
*/
def mapWritten[M](f: L => M)(implicit functorF: Functor[F]): WriterT[F, M, V] =
mapBoth((l, v) => (f(l), v))
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(123)).tell("log")
* scala> writer.swap
* res0: WriterT[Option, Int, String] = WriterT(Some((123,log)))
* }}}
*/
def swap(implicit functorF: Functor[F]): WriterT[F, V, L] =
mapBoth((l, v) => (v, l))
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(123)).tell("error")
* scala> writer.reset
* res0: WriterT[Option, String, Int] = WriterT(Some((,123)))
* }}}
*/
def reset(implicit monoidL: Monoid[L], functorF: Functor[F]): WriterT[F, L, V] =
mapWritten(_ => monoidL.empty)
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(456)).tell("log...")
* scala> writer.show
* res0: String = Some((log...,456))
* }}}
*/
def show(implicit F: Show[F[(L, V)]]): String = F.show(run)
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(123)).tell("hi")
* scala> writer.foldLeft(456)((acc,v) => acc + v)
* res0: Int = 579
* }}}
*/
def foldLeft[C](c: C)(f: (C, V) => C)(implicit F: Foldable[F]): C =
F.foldLeft(run, c)((z, lv) => f(z, lv._2))
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.Eval
* scala> import cats.implicits._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(123)).tell("hi")
* scala> writer
* | .foldRight(Eval.now(456))((v,c) => c.map(_ + v))
* | .value
* res0: Int = 579
* }}}
*/
def foldRight[C](lc: Eval[C])(f: (V, Eval[C]) => Eval[C])(implicit F: Foldable[F]): Eval[C] =
F.foldRight(run, lc)((lv, z) => f(lv._2, z))
/**
* Example:
* {{{
* scala> import cats.data.WriterT
* scala> import cats.implicits._
*
* scala> val writer = WriterT.liftF[Option, String, Int](Some(123)).tell("hi")
* scala> writer.traverse[List,Int](i => List(i))
* res0: List[WriterT[Option, String, Int]] = List(WriterT(Some((hi,123))))
* }}}
*/
def traverse[G[_], V1](f: V => G[V1])(implicit F: Traverse[F], G: Applicative[G]): G[WriterT[F, L, V1]] =
G.map(
F.traverse(run)(lv => G.tupleLeft(f(lv._2), lv._1))
)(WriterT.apply)
}
object WriterT extends WriterTInstances with WriterTFunctions with WriterTFunctions0 {
def liftF[F[_], L, V](fv: F[V])(implicit monoidL: Monoid[L], F: Applicative[F]): WriterT[F, L, V] =
WriterT(F.map(fv)(v => (monoidL.empty, v)))
/**
* Same as [[liftF]], but expressed as a FunctionK for use with mapK
* {{{
* scala> import cats._, data._, implicits._
* scala> val a: OptionT[Eval, Int] = 1.pure[OptionT[Eval, *]]
* scala> val b: OptionT[WriterT[Eval, String, *], Int] = a.mapK(WriterT.liftK)
* scala> b.value.run.value
* res0: (String, Option[Int]) = ("",Some(1))
* }}}
*/
def liftK[F[_], L](implicit monoidL: Monoid[L], F: Applicative[F]): F ~> WriterT[F, L, *] =
λ[F ~> WriterT[F, L, *]](WriterT.liftF(_))
@deprecated("Use liftF instead", "1.0.0-RC2")
def lift[F[_], L, V](fv: F[V])(implicit monoidL: Monoid[L], F: Applicative[F]): WriterT[F, L, V] =
WriterT(F.map(fv)(v => (monoidL.empty, v)))
}
sealed abstract private[data] class WriterTInstances extends WriterTInstances0 {
implicit def catsDataCommutativeMonadForWriterT[F[_], L](
implicit F: CommutativeMonad[F],
L: CommutativeMonoid[L]
): CommutativeMonad[WriterT[F, L, *]] =
new WriterTMonad[F, L] with CommutativeMonad[WriterT[F, L, *]] {
implicit val F0: Monad[F] = F
implicit val L0: Monoid[L] = L
}
implicit def catsDataTraverseForWriterTId[L](implicit F: Traverse[Id]): Traverse[WriterT[Id, L, *]] =
catsDataTraverseForWriterT[Id, L](F)
implicit def catsDataDeferForWriterT[F[_], L](implicit F: Defer[F]): Defer[WriterT[F, L, *]] =
new Defer[WriterT[F, L, *]] {
def defer[A](fa: => WriterT[F, L, A]): WriterT[F, L, A] =
WriterT(F.defer(fa.run))
}
}
sealed abstract private[data] class WriterTInstances0 extends WriterTInstances1 {
implicit def catsDataTraverseForWriterT[F[_], L](implicit F: Traverse[F]): Traverse[WriterT[F, L, *]] =
new WriterTTraverse[F, L] {
val F0: Traverse[F] = F
}
implicit def catsDataFoldableForWriterTId[L](implicit F: Foldable[Id]): Foldable[WriterT[Id, L, *]] =
catsDataFoldableForWriterT[Id, L](F)
}
sealed abstract private[data] class WriterTInstances1 extends WriterTInstances2 {
implicit def catsDataMonadErrorForWriterT[F[_], L, E](implicit F: MonadError[F, E],
L: Monoid[L]): MonadError[WriterT[F, L, *], E] =
new WriterTMonadError[F, L, E] {
implicit val F0: MonadError[F, E] = F
implicit val L0: Monoid[L] = L
}
implicit def catsDataParallelForWriterT[M[_], L: Monoid](
implicit P: Parallel[M]
): Parallel.Aux[WriterT[M, L, *], WriterT[P.F, L, *]] = new Parallel[WriterT[M, L, *]] {
type F[x] = WriterT[P.F, L, x]
implicit val monadM: Monad[M] = P.monad
def applicative: Applicative[WriterT[P.F, L, *]] = catsDataApplicativeForWriterT(P.applicative, Monoid[L])
def monad: Monad[WriterT[M, L, *]] = catsDataMonadForWriterT
def sequential: WriterT[P.F, L, *] ~> WriterT[M, L, *] =
λ[WriterT[P.F, L, *] ~> WriterT[M, L, *]](wfl => WriterT(P.sequential(wfl.run)))
def parallel: WriterT[M, L, *] ~> WriterT[P.F, L, *] =
λ[WriterT[M, L, *] ~> WriterT[P.F, L, *]](wml => WriterT(P.parallel(wml.run)))
}
implicit def catsDataEqForWriterTId[L: Eq, V: Eq]: Eq[WriterT[Id, L, V]] =
catsDataEqForWriterT[Id, L, V]
implicit def catsDataBifunctorForWriterT[F[_]: Functor]: Bifunctor[WriterT[F, *, *]] =
new Bifunctor[WriterT[F, *, *]] {
def bimap[A, B, C, D](fab: WriterT[F, A, B])(f: A => C, g: B => D): WriterT[F, C, D] =
fab.bimap(f, g)
}
implicit def catsDataShowForWriterT[F[_], L, V](implicit F: Show[F[(L, V)]]): Show[WriterT[F, L, V]] =
new Show[WriterT[F, L, V]] {
override def show(f: WriterT[F, L, V]): String = f.show
}
implicit def catsDataMonoidForWriterTId[L: Monoid, V: Monoid]: Monoid[WriterT[Id, L, V]] =
catsDataMonoidForWriterT[Id, L, V]
implicit def catsDataFoldableForWriterT[F[_], L](implicit F: Foldable[F]): Foldable[WriterT[F, L, *]] =
new WriterTFoldable[F, L] {
val F0: Foldable[F] = F
}
}
sealed abstract private[data] class WriterTInstances2 extends WriterTInstances3 {
implicit def catsDataMonadForWriterTId[L: Monoid]: Monad[WriterT[Id, L, *]] =
catsDataMonadForWriterT[Id, L]
implicit def catsDataEqForWriterT[F[_], L, V](implicit F: Eq[F[(L, V)]]): Eq[WriterT[F, L, V]] =
Eq.by[WriterT[F, L, V], F[(L, V)]](_.run)
implicit def catsDataSemigroupForWriterTId[L: Semigroup, V: Semigroup]: Semigroup[WriterT[Id, L, V]] =
catsDataSemigroupForWriterT[Id, L, V]
implicit def catsDataComonadForWriterTId[L](implicit F: Comonad[Id]): Comonad[WriterT[Id, L, *]] =
catsDataComonadForWriterT[Id, L](F)
}
sealed abstract private[data] class WriterTInstances3 extends WriterTInstances4 {
implicit def catsDataMonadForWriterT[F[_], L](implicit F: Monad[F], L: Monoid[L]): Monad[WriterT[F, L, *]] =
new WriterTMonad[F, L] {
implicit val F0: Monad[F] = F
implicit val L0: Monoid[L] = L
}
implicit def catsDataMonoidForWriterT[F[_], L, V](implicit W: Monoid[F[(L, V)]]): Monoid[WriterT[F, L, V]] =
new WriterTMonoid[F, L, V] {
implicit val F0: Monoid[F[(L, V)]] = W
}
implicit def catsDataCoflatMapForWriterTId[L]: CoflatMap[WriterT[Id, L, *]] =
catsDataCoflatMapForWriterT[Id, L]
}
sealed abstract private[data] class WriterTInstances4 extends WriterTInstances5 {
implicit def catsDataFlatMapForWriterTId[L: Semigroup]: FlatMap[WriterT[Id, L, *]] =
catsDataFlatMapForWriterT2[Id, L]
}
sealed abstract private[data] class WriterTInstances5 extends WriterTInstances6 {
implicit def catsDataFlatMapForWriterT1[F[_], L](implicit F: FlatMap[F], L: Monoid[L]): FlatMap[WriterT[F, L, *]] =
new WriterTFlatMap1[F, L] {
implicit val F0: FlatMap[F] = F
implicit val L0: Monoid[L] = L
}
implicit def catsDataSemigroupForWriterT[F[_], L, V](implicit W: Semigroup[F[(L, V)]]): Semigroup[WriterT[F, L, V]] =
new WriterTSemigroup[F, L, V] {
implicit val F0: Semigroup[F[(L, V)]] = W
}
}
sealed abstract private[data] class WriterTInstances6 extends WriterTInstances7 {
implicit def catsDataApplicativeErrorForWriterT[F[_], L, E](implicit F: ApplicativeError[F, E],
L: Monoid[L]): ApplicativeError[WriterT[F, L, *], E] =
new WriterTApplicativeError[F, L, E] {
implicit val F0: ApplicativeError[F, E] = F
implicit val L0: Monoid[L] = L
}
}
sealed abstract private[data] class WriterTInstances7 extends WriterTInstances8 {
implicit def catsDataAlternativeForWriterT[F[_], L](implicit F: Alternative[F],
L: Monoid[L]): Alternative[WriterT[F, L, *]] =
new WriterTAlternative[F, L] {
implicit val F0: Alternative[F] = F
implicit val L0: Monoid[L] = L
}
implicit def catsDataContravariantMonoidalForWriterT[F[_], L](
implicit F: ContravariantMonoidal[F]
): ContravariantMonoidal[WriterT[F, L, *]] =
new WriterTContravariantMonoidal[F, L] {
implicit val F0: ContravariantMonoidal[F] = F
}
}
sealed abstract private[data] class WriterTInstances8 extends WriterTInstances9 {
implicit def catsDataMonoidKForWriterT[F[_], L](implicit F: MonoidK[F]): MonoidK[WriterT[F, L, *]] =
new WriterTMonoidK[F, L] {
implicit val F0: MonoidK[F] = F
}
implicit def catsDataFlatMapForWriterT2[F[_], L](implicit F: Monad[F], L: Semigroup[L]): FlatMap[WriterT[F, L, *]] =
new WriterTFlatMap2[F, L] {
implicit val F0: Monad[F] = F
implicit val L0: Semigroup[L] = L
}
implicit def catsDataContravariantForWriterT[F[_], L](implicit F: Contravariant[F]): Contravariant[WriterT[F, L, *]] =
new WriterTContravariant[F, L] {
implicit val F0: Contravariant[F] = F
}
}
sealed abstract private[data] class WriterTInstances9 extends WriterTInstances10 {
implicit def catsDataSemigroupKForWriterT[F[_], L](implicit F: SemigroupK[F]): SemigroupK[WriterT[F, L, *]] =
new WriterTSemigroupK[F, L] {
implicit val F0: SemigroupK[F] = F
}
implicit def catsDataApplicativeForWriterT[F[_], L](implicit F: Applicative[F],
L: Monoid[L]): Applicative[WriterT[F, L, *]] =
new WriterTApplicative[F, L] {
implicit val F0: Applicative[F] = F
implicit val L0: Monoid[L] = L
}
implicit def catsDataInvariantForWriterT[F[_], L](implicit F0: Invariant[F]): Invariant[WriterT[F, L, *]] =
new WriterTInvariant[F, L] { implicit val F = F0 }
}
sealed abstract private[data] class WriterTInstances10 extends WriterTInstances11 {
implicit def catsDataApplyForWriterT[F[_], L](implicit F: Apply[F], L: Semigroup[L]): Apply[WriterT[F, L, *]] =
new WriterTApply[F, L] {
implicit val F0: Apply[F] = F
implicit val L0: Semigroup[L] = L
}
}
sealed abstract private[data] class WriterTInstances11 extends WriterTInstances12 {
implicit def catsDataComonadForWriterT[F[_], L](implicit F: Comonad[F]): Comonad[WriterT[F, L, *]] =
new WriterTComonad[F, L] {
implicit val F0: Comonad[F] = F
}
}
sealed abstract private[data] class WriterTInstances12 {
implicit def catsDataCoflatMapForWriterT[F[_], L](implicit F: Functor[F]): CoflatMap[WriterT[F, L, *]] =
new WriterTCoflatMap[F, L] {
implicit val F0: Functor[F] = F
}
}
sealed private[data] trait WriterTFunctor[F[_], L] extends Functor[WriterT[F, L, *]] {
implicit def F0: Functor[F]
override def map[A, B](fa: WriterT[F, L, A])(f: A => B): WriterT[F, L, B] =
fa.map(f)
}
sealed private[data] trait WriterTContravariant[F[_], L] extends Contravariant[WriterT[F, L, *]] {
implicit def F0: Contravariant[F]
override def contramap[A, B](fa: WriterT[F, L, A])(f: B => A): WriterT[F, L, B] =
fa.contramap(f)
}
sealed private[data] trait WriterTInvariant[F[_], L] extends Invariant[WriterT[F, L, *]] {
implicit def F: Invariant[F]
override def imap[A, B](fa: WriterT[F, L, A])(f: A => B)(g: B => A): WriterT[F, L, B] =
fa.imap(f)(g)
}
sealed private[data] trait WriterTApply[F[_], L] extends WriterTFunctor[F, L] with Apply[WriterT[F, L, *]] {
implicit override def F0: Apply[F]
implicit def L0: Semigroup[L]
def ap[A, B](f: WriterT[F, L, A => B])(fa: WriterT[F, L, A]): WriterT[F, L, B] =
fa.ap(f)
override def map2Eval[A, B, Z](fa: WriterT[F, L, A],
fb: Eval[WriterT[F, L, B]])(f: (A, B) => Z): Eval[WriterT[F, L, Z]] =
F0.map2Eval(fa.run, fb.map(_.run)) { case ((la, a), (lb, b)) => (L0.combine(la, lb), f(a, b)) }
.map(WriterT(_)) // F0 may have a lazy map2Eval
override def product[A, B](fa: WriterT[F, L, A], fb: WriterT[F, L, B]): WriterT[F, L, (A, B)] =
WriterT(F0.map(F0.product(fa.run, fb.run)) { case ((l1, a), (l2, b)) => (L0.combine(l1, l2), (a, b)) })
}
sealed private[data] trait WriterTFlatMap1[F[_], L] extends WriterTApply[F, L] with FlatMap[WriterT[F, L, *]] {
implicit override def F0: FlatMap[F]
implicit def L0: Monoid[L]
override def ap[A, B](f: WriterT[F, L, A => B])(fa: WriterT[F, L, A]): WriterT[F, L, B] =
super[WriterTApply].ap(f)(fa)
def flatMap[A, B](fa: WriterT[F, L, A])(f: A => WriterT[F, L, B]): WriterT[F, L, B] =
fa.flatMap(f)
def tailRecM[A, B](a: A)(fn: A => WriterT[F, L, Either[A, B]]): WriterT[F, L, B] = {
def step(la: (L, A)): F[Either[(L, A), (L, B)]] = {
val flv: F[(L, Either[A, B])] = fn(la._2).run
F0.map(flv) {
case (l, Left(a)) =>
val combineL = L0.combine(la._1, l)
Left((combineL, a))
case (l, Right(b)) =>
val combineL = L0.combine(la._1, l)
Right((combineL, b))
}
}
WriterT(F0.tailRecM((L0.empty, a))(step))
}
}
sealed private[data] trait WriterTFlatMap2[F[_], L] extends WriterTApply[F, L] with FlatMap[WriterT[F, L, *]] {
implicit override def F0: Monad[F]
implicit def L0: Semigroup[L]
def flatMap[A, B](fa: WriterT[F, L, A])(f: A => WriterT[F, L, B]): WriterT[F, L, B] =
fa.flatMap(f)
def tailRecM[A, B](a: A)(fn: A => WriterT[F, L, Either[A, B]]): WriterT[F, L, B] = {
def step(la: (L, A)): F[Either[(L, A), (L, B)]] = {
val flv: F[(L, Either[A, B])] = fn(la._2).run
F0.map(flv) {
case (l, Left(a)) =>
val combineL = L0.combine(la._1, l)
Left((combineL, a))
case (l, Right(b)) =>
val combineL = L0.combine(la._1, l)
Right((combineL, b))
}
}
val init = fn(a).run
val res: F[(L, B)] = F0.flatMap(init) {
case (l, Right(b)) => F0.pure((l, b))
case (l, Left(a)) => F0.tailRecM((l, a))(step)
}
WriterT(res)
}
}
sealed private[data] trait WriterTApplicative[F[_], L] extends WriterTApply[F, L] with Applicative[WriterT[F, L, *]] {
implicit override def F0: Applicative[F]
implicit override def L0: Monoid[L]
def pure[A](a: A): WriterT[F, L, A] =
WriterT.value[F, L, A](a)
}
sealed private[data] trait WriterTMonad[F[_], L]
extends WriterTApplicative[F, L]
with WriterTFlatMap1[F, L]
with Monad[WriterT[F, L, *]] {
implicit override def F0: Monad[F]
implicit override def L0: Monoid[L]
}
sealed private[data] trait WriterTApplicativeError[F[_], L, E]
extends ApplicativeError[WriterT[F, L, *], E]
with WriterTApplicative[F, L] {
implicit override def F0: ApplicativeError[F, E]
def raiseError[A](e: E): WriterT[F, L, A] = WriterT(F0.raiseError[(L, A)](e))
def handleErrorWith[A](fa: WriterT[F, L, A])(f: E => WriterT[F, L, A]): WriterT[F, L, A] =
WriterT(F0.handleErrorWith(fa.run)(e => f(e).run))
}
sealed private[data] trait WriterTMonadError[F[_], L, E]
extends MonadError[WriterT[F, L, *], E]
with WriterTMonad[F, L]
with WriterTApplicativeError[F, L, E] {
implicit override def F0: MonadError[F, E]
}
sealed private[data] trait WriterTSemigroupK[F[_], L] extends SemigroupK[WriterT[F, L, *]] {
implicit def F0: SemigroupK[F]
def combineK[A](x: WriterT[F, L, A], y: WriterT[F, L, A]): WriterT[F, L, A] =
WriterT(F0.combineK(x.run, y.run))
}
sealed private[data] trait WriterTMonoidK[F[_], L] extends MonoidK[WriterT[F, L, *]] with WriterTSemigroupK[F, L] {
implicit override def F0: MonoidK[F]
def empty[A]: WriterT[F, L, A] = WriterT(F0.empty)
}
sealed private[data] trait WriterTAlternative[F[_], L]
extends Alternative[WriterT[F, L, *]]
with WriterTMonoidK[F, L]
with WriterTApplicative[F, L] {
implicit override def F0: Alternative[F]
}
sealed private[data] trait WriterTContravariantMonoidal[F[_], L] extends ContravariantMonoidal[WriterT[F, L, *]] {
implicit def F0: ContravariantMonoidal[F]
override def unit: WriterT[F, L, Unit] = WriterT(F0.trivial[(L, Unit)])
override def contramap[A, B](fa: WriterT[F, L, A])(f: B => A): WriterT[F, L, B] =
fa.contramap(f)
override def product[A, B](fa: WriterT[F, L, A], fb: WriterT[F, L, B]): WriterT[F, L, (A, B)] =
WriterT(
F0.contramap(F0.product(fa.run, fb.run))(
(t: (L, (A, B))) =>
t match {
case (l, (a, b)) => ((l, a), (l, b))
}
)
)
}
sealed private[data] trait WriterTSemigroup[F[_], L, A] extends Semigroup[WriterT[F, L, A]] {
implicit def F0: Semigroup[F[(L, A)]]
def combine(x: WriterT[F, L, A], y: WriterT[F, L, A]): WriterT[F, L, A] =
WriterT(F0.combine(x.run, y.run))
}
sealed private[data] trait WriterTMonoid[F[_], L, A] extends Monoid[WriterT[F, L, A]] with WriterTSemigroup[F, L, A] {
implicit override def F0: Monoid[F[(L, A)]]
def empty: WriterT[F, L, A] = WriterT(F0.empty)
}
sealed private[data] trait WriterTCoflatMap[F[_], L] extends CoflatMap[WriterT[F, L, *]] with WriterTFunctor[F, L] {
def coflatMap[A, B](fa: WriterT[F, L, A])(f: WriterT[F, L, A] => B): WriterT[F, L, B] = fa.map(_ => f(fa))
}
sealed private[data] trait WriterTFoldable[F[_], L] extends Foldable[WriterT[F, L, *]] {
implicit def F0: Foldable[F]
def foldLeft[A, B](fa: WriterT[F, L, A], b: B)(f: (B, A) => B): B = fa.foldLeft(b)(f)
def foldRight[A, B](fa: WriterT[F, L, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = fa.foldRight(lb)(f)
}
sealed private[data] trait WriterTTraverse[F[_], L]
extends Traverse[WriterT[F, L, *]]
with WriterTFoldable[F, L]
with WriterTFunctor[F, L] {
implicit override def F0: Traverse[F]
def traverse[G[_]: Applicative, A, B](fa: WriterT[F, L, A])(f: A => G[B]): G[WriterT[F, L, B]] = fa.traverse(f)
}
sealed private[data] trait WriterTComonad[F[_], L] extends Comonad[WriterT[F, L, *]] with WriterTCoflatMap[F, L] {
implicit override def F0: Comonad[F]
def extract[A](fa: WriterT[F, L, A]): A = F0.extract(F0.map(fa.run)(_._2))
}
// new trait for binary compatibility
private[data] trait WriterTFunctions0 {
def listen[F[_], L, V](writerTFLV: WriterT[F, L, V])(implicit functorF: Functor[F]): WriterT[F, L, (V, L)] =
writerTFLV.listen
}
private[data] trait WriterTFunctions {
def putT[F[_], L, V](vf: F[V])(l: L)(implicit functorF: Functor[F]): WriterT[F, L, V] =
WriterT(functorF.map(vf)(v => (l, v)))
def put[F[_], L, V](v: V)(l: L)(implicit applicativeF: Applicative[F]): WriterT[F, L, V] =
WriterT.putT[F, L, V](applicativeF.pure(v))(l)
def tell[F[_], L](l: L)(implicit applicativeF: Applicative[F]): WriterT[F, L, Unit] =
WriterT.put[F, L, Unit](())(l)
def value[F[_], L, V](v: V)(implicit applicativeF: Applicative[F], monoidL: Monoid[L]): WriterT[F, L, V] =
WriterT.put[F, L, V](v)(monoidL.empty)
def valueT[F[_], L, V](vf: F[V])(implicit functorF: Functor[F], monoidL: Monoid[L]): WriterT[F, L, V] =
WriterT.putT[F, L, V](vf)(monoidL.empty)
}