
scalaz.UnwriterT.scala Maven / Gradle / Ivy
The newest version!
package org.specs2.internal.scalaz
import Id._
/**
* This data type is isomorphic to `WriterT`, however, it is NOT a monad.
*
* It implements flatMap+map and drops the write value. There is no `Monoid` or `Semigroup` required. There is no `point` operation.
* You can switch between `WriterT` and `UnwriterT` with `unary_+` and `unary_-`.
*/
sealed trait UnwriterT[F[+_], +U, +A] { self =>
val run: F[(U, A)]
import UnwriterT._
def on: WriterT[F, U, A] =
WriterT(run)
/** alias for `on` */
def unary_+ : WriterT[F, U, A] =
WriterT(run)
def mapValue[X, B](f: ((U, A)) => (X, B))(implicit F: Functor[F]): UnwriterT[F, X, B] =
unwriterT(F.map(run)(f))
def mapUnwritten[X](f: U => X)(implicit ftr: Functor[F]): UnwriterT[F, X, A] =
mapValue(wa => (f(wa._1), wa._2))
def unwritten(implicit F: Functor[F]): F[U] =
F.map(run)(_._1)
def value(implicit F: Functor[F]): F[A] =
F.map(run)(_._2)
def swap(implicit F: Functor[F]): UnwriterT[F, A, U] =
mapValue(wa => (wa._2, wa._1))
def map[B](f: A => B)(implicit F: Functor[F]): UnwriterT[F, U, B] =
unwriterT(F.map(run)(wa => (wa._1, f(wa._2))))
def foreach[B](f: A => Unit)(implicit E: Each[F]): Unit =
E.each(run)(wa => f(wa._2))
def ap[B, UU >: U](f: => UnwriterT[F, UU, A => B])(implicit F: Apply[F]): UnwriterT[F, UU, B] =
unwriterT {
F.apply2(f.run, run) {
case ((w1, fab), (_, a)) => (w1, fab(a))
}
}
def flatMap[B, UU >: U](f: A => UnwriterT[F, UU, B])(implicit F: Bind[F]): UnwriterT[F, UU, B] =
unwriterT(F.bind(run){wa =>
val z = f(wa._2).run
F.map(z)(wb => (wa._1, wb._2))
})
def traverse[G[+_] , B](f: A => G[B])(implicit G: Applicative[G], F: Traverse[F]): G[UnwriterT[F, U, B]] = {
G.map(F.traverse(run){
case (w, a) => G.map(f(a))(b => (w, b))
})(UnwriterT(_))
}
def foldRight[B](z: => B)(f: (A, => B) => B)(implicit F: Foldable[F]) =
F.foldr(run, z) { a => b =>
f(a._2, b)
}
def bimap[C, D](f: (U) => C, g: (A) => D)(implicit F: Functor[F]) =
unwriterT[F, C, D](F.map(run)({
case (a, b) => (f(a), g(b))
}))
def bitraverse[G[_], C, D](f: (U) => G[C], g: (A) => G[D])(implicit G: Applicative[G], F: Traverse[F]) =
G.map(F.traverse[G, (U, A), (C, D)](run) {
case (a, b) => G.apply2(f(a), g(b))((_, _))
})(unwriterT(_))
def wpoint[G[+_]](implicit F: Functor[F], P: Pointed[G]): UnwriterT[F, G[U], A] =
unwriterT(F.map(self.run) {
case (u, a) => (P.point(u), a)
})
}
object UnwriterT extends UnwriterTFunctions with UnwriterTInstances {
def apply[F[+_], W, A](v: F[(W, A)]): UnwriterT[F, W, A] =
unwriterT(v)
}
trait UnwriterTInstances2 {
implicit def unwriterTFunctor[F[+_], W](implicit F0: Functor[F]) = new UnwriterTFunctor[F, W] {
implicit def F = F0
}
}
trait UnwriterTInstances1 extends UnwriterTInstances2 {
implicit def unwriterTApply[F[+_], W](implicit F0: Apply[F]) = new UnwriterTApply[F, W] {
implicit def F = F0
}
}
trait UnwriterTInstances0 extends UnwriterTInstances1 {
implicit def unwriterTBifunctor[F[+_]](implicit F0: Functor[F]) = new UnwriterTBifunctor[F] {
implicit def F = F0
}
implicit def unwriterTBind[F[+_], W](implicit F0: Bind[F]) = new UnwriterTBind[F, W] {
implicit def F = F0
}
implicit def unwriterTCopointed[F[+_], W](implicit F0: Copointed[F]) = new UnwriterTCopointed[F, W] {
implicit def F = F0
}
implicit def unwriterTFoldable[F[+_], W](implicit F0: Foldable[F]) = new UnwriterTFoldable[F, W] {
implicit def F = F0
}
implicit def unwriterTEqual[F[+_], W, A](implicit E: Equal[F[(W, A)]]) = E.contramap((_: UnwriterT[F, W, A]).run)
}
trait UnwriterTInstances extends UnwriterTInstances0 {
implicit def unwriterTBitraverse[F[+_]](implicit F0: Traverse[F]) = new UnwriterTBitraverse[F] {
implicit def F = F0
}
implicit def unwriterComonad[W] = new UnwriterComonad[W] {
implicit def F = implicitly
}
implicit def unwriterTTraverse[F[+_], W](implicit F0: Traverse[F]) = new UnwriterTTraverse[F, W] {
implicit def F = F0
}
implicit def unwriterTIndex[W] = new UnwriterTIndex[W] {
}
implicit def unwriterTEach[F[+_], W](implicit F0: Each[F]) = new UnwriterTEach[F, W] {
implicit def F = F0
}
implicit def unwriterEqual[W, A](implicit W: Equal[W], A: Equal[A]) = {
import std.tuple._
Equal[(W, A)].contramap((_: Unwriter[W, A]).run)
}
}
trait UnwriterTFunctions {
def unwriterT[F[+_], W, A](v: F[(W, A)]): UnwriterT[F, W, A] = new UnwriterT[F, W, A] {
val run = v
}
import StoreT._
def unwriter[W, A](v: (W, A)): Unwriter[W, A] =
unwriterT[Id, W, A](v)
def tell[W](w: W): Unwriter[W, Unit] = unwriter(w -> ())
def unput[F[+_], W, A](value: F[A])(w: W)(implicit F: Functor[F]): UnwriterT[F, W, A] =
UnwriterT(F.map(value)(a => (w, a)))
/** Puts the written value that is produced by applying the given function into a unwriter transformer and associates with `value` */
def unputWith[F[+_], W, A](value: F[A])(w: A => W)(implicit F: Functor[F]): UnwriterT[F, W, A] =
UnwriterT(F.map(value)(a => (w(a), a)))
def unwriterUL[F[+_], W, A](implicit MF: Pointed[F]): LensT[F, UnwriterT[F, W, A], W] =
LensT(x => MF.map(x.run) {
case (w, a) => Store((ww: W) => UnwriterT(MF.point(ww, a)), w)
})
def unwriterAL[F[+_], W, A](implicit MF: Pointed[F]): LensT[F, UnwriterT[F, W, A], A] =
LensT(x => MF.map(x.run) {
case (w, a) => Store((aa: A) => UnwriterT(MF.point(w, aa)), a)
})
}
//
// Type class implementation traits
//
trait UnwriterTFunctor[F[+_], W] extends Functor[({type λ[+α]=UnwriterT[F, W, α]})#λ] {
implicit def F: Functor[F]
override def map[A, B](fa: UnwriterT[F, W, A])(f: (A) => B) = fa map f
}
trait UnwriterTApply[F[+_], W] extends Apply[({type λ[+α]=UnwriterT[F, W, α]})#λ] with UnwriterTFunctor[F, W] {
implicit def F: Apply[F]
override def ap[A, B](fa: => UnwriterT[F, W, A])(f: => UnwriterT[F, W, (A) => B]) = fa ap f
}
trait UnwriterTEach[F[+_], W] extends Each[({type λ[+α]=UnwriterT[F, W, α]})#λ] {
implicit def F: Each[F]
def each[A](fa: UnwriterT[F, W, A])(f: (A) => Unit) = fa foreach f
}
// TODO does Index it make sense for F other than Id?
trait UnwriterTIndex[W] extends Index[({type λ[+α]=UnwriterT[Id, W, α]})#λ] {
def index[A](fa: UnwriterT[Id, W, A], i: Int) = if(i == 0) Some(fa.value) else None
}
trait UnwriterTBind[F[+_], W] extends Bind[({type λ[+α]=UnwriterT[F, W, α]})#λ] with UnwriterTApply[F, W] {
implicit def F: Bind[F]
def bind[A, B](fa: UnwriterT[F, W, A])(f: (A) => UnwriterT[F, W, B]) = fa flatMap f
}
trait UnwriterTFoldable[F[+_], W] extends Foldable.FromFoldr[({type λ[+α]=UnwriterT[F, W, α]})#λ] {
implicit def F: Foldable[F]
override def foldRight[A, B](fa: UnwriterT[F, W, A], z: => B)(f: (A, => B) => B) = fa.foldRight(z)(f)
}
trait UnwriterTTraverse[F[+_], W] extends Traverse[({type λ[+α]=UnwriterT[F, W, α]})#λ] with UnwriterTFoldable[F, W] {
implicit def F: Traverse[F]
def traverseImpl[G[+_]: Applicative, A, B](fa: UnwriterT[F, W, A])(f: (A) => G[B]) = fa traverse f
}
trait UnwriterTBifunctor[F[+_]] extends Bifunctor[({type λ[+α, +β]=UnwriterT[F, α, β]})#λ] {
implicit def F: Functor[F]
override def bimap[A, B, C, D](fab: UnwriterT[F, A, B])(f: (A) => C, g: (B) => D) =
fab.bimap(f, g)
}
trait UnwriterTBitraverse[F[+_]] extends Bitraverse[({type λ[+α, +β]=UnwriterT[F, α, β]})#λ] with UnwriterTBifunctor[F] {
implicit def F: Traverse[F]
def bitraverseImpl[G[_]: Applicative, A, B, C, D](fab: UnwriterT[F, A, B])(f: (A) => G[C], g: (B) => G[D]) =
fab.bitraverse(f, g)
}
trait UnwriterTCopointed[F[+_], W] extends Copointed[({type λ[+α] = UnwriterT[F, W, α]})#λ] with UnwriterTFunctor[F, W] {
implicit def F: Copointed[F]
def copoint[A](p: UnwriterT[F, W, A]): A = F.copoint(p.value)
}
trait UnwriterComonad[W] extends Comonad[({type λ[+α] = Unwriter[W, α]})#λ] with UnwriterTCopointed[Id, W] {
override def cojoin[A](fa: Unwriter[W, A]): Unwriter[W, Unwriter[W, A]] =
Unwriter(fa.unwritten, fa)
override def cobind[A, B](fa: Unwriter[W, A])(f: (Unwriter[W, A]) => B): Unwriter[W, B] =
Unwriter(fa.unwritten, f(fa))
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy