-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add IdT, the identity monad transformer
- Loading branch information
Showing
1 changed file
with
93 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package cats | ||
package data | ||
|
||
/** | ||
* `IdT[F[_], A]` is the identity monad transformer. | ||
*/ | ||
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)) | ||
|
||
def flatMap[B](f: A => IdT[F, B])(implicit F: Monad[F]): IdT[F, B] = | ||
IdT(F.flatMap(value)(f.andThen(_.value))) | ||
|
||
def flatMapF[B](f: A => F[B])(implicit F: Monad[F]): IdT[F, B] = | ||
IdT(F.flatMap(value)(f)) | ||
|
||
def foldLeft[B](b: B)(f: (B, A) => B)(implicit F: Foldable[F]): B = | ||
F.foldLeft(value, b)(f) | ||
|
||
def foldRight[B](lb: Eval[B])(f: (A, Eval[B]) => Eval[B])(implicit F: Foldable[F]): Eval[B] = | ||
F.foldRight(value, lb)(f) | ||
|
||
def traverse[G[_], B](f: A => G[B])(implicit F: Traverse[F], G: Applicative[G]): G[IdT[F, B]] = | ||
G.map(F.traverse(value)(f))(IdT(_)) | ||
|
||
def ap[B](f: IdT[F, A => B])(implicit F: Apply[F]): IdT[F, B] = | ||
IdT(F.ap(value)(f.value)) | ||
|
||
} | ||
|
||
object IdT extends IdTInstances { | ||
|
||
def pure[F[_], A](a: A)(implicit F: Applicative[F]): IdT[F, A] = | ||
IdT(F.pure(a)) | ||
} | ||
|
||
private[data] sealed trait IdTFunctor[F[_]] extends Functor[IdT[F, ?]] { | ||
implicit val F0: Functor[F] | ||
|
||
def map[A, B](fa: IdT[F, A])(f: A => B): IdT[F, B] = | ||
fa.map(f) | ||
} | ||
|
||
private[data] sealed trait IdTMonad[F[_]] extends Monad[IdT[F, ?]] { | ||
implicit val F0: Monad[F] | ||
|
||
def pure[A](a: A): IdT[F, A] = | ||
IdT.pure(a) | ||
|
||
def flatMap[A, B](fa: IdT[F, A])(f: A => IdT[F, B]): IdT[F, B] = | ||
fa.flatMap(f) | ||
} | ||
|
||
private[data] sealed trait IdTFoldable[F[_]] extends Foldable[IdT[F, ?]] { | ||
implicit val F0: Foldable[F] | ||
|
||
def foldLeft[A, B](fa: IdT[F, A], b: B)(f: (B, A) => B): B = | ||
fa.foldLeft(b)(f) | ||
|
||
def foldRight[A, B](fa: IdT[F, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = | ||
fa.foldRight(lb)(f) | ||
} | ||
|
||
private[data] sealed trait IdTTraverse[F[_]] extends Traverse[IdT[F, ?]] with IdTFoldable[F] { | ||
implicit val F0: Traverse[F] | ||
|
||
def traverse[G[_]: Applicative, A, B](fa: IdT[F, A])(f: A => G[B]): G[IdT[F, B]] = | ||
fa.traverse(f) | ||
} | ||
|
||
private[data] sealed abstract class IdTInstances { | ||
implicit def idTFunctor[F[_]](implicit F: Functor[F]): Functor[IdT[F, ?]] = | ||
new IdTFunctor[F] { | ||
implicit val F0: Functor[F] = F | ||
} | ||
|
||
implicit def idTMonad[F[_]](implicit F: Monad[F]): Monad[IdT[F, ?]] = | ||
new IdTMonad[F] { | ||
implicit val F0: Monad[F] = F | ||
} | ||
|
||
implicit def idTTraverse[F[_]](implicit F: Traverse[F]): Traverse[IdT[F, ?]] = | ||
new IdTTraverse[F] { | ||
implicit val F0: Traverse[F] = F | ||
} | ||
|
||
implicit def idTEq[F[_], A](implicit F: Eq[F[A]]): Eq[IdT[F, A]] = | ||
F.on(_.value) | ||
|
||
implicit def idTShow[F[_], A](implicit F: Show[F[A]]): Show[IdT[F, A]] = | ||
functor.Contravariant[Show].contramap(F)(_.value) | ||
} |