The name flatten
should remind you of the functions of the same name on many
classes in the standard library.
Unlike Functor
s and Applicative
s, you cannot derive a monad instance for a generic M[N[_]]
where both M[_]
and N[_]
have an instance of a monad.
Unlike Functor
s and Applicative
s, you cannot derive a monad instance for a generic M[N[_]]
where both M[_]
and N[_]
have an instance of a monad.
However, it is common to want to compose the effects of both M[_]
and N[_]
. One way of expressing this
is to provide instructions on how to compose any outer monad (F
in the following example) with a specific
inner monad (Option
in the following example).
case class OptionT[F[_], A](value: F[Option[A]]) implicit def optionTMonad[F[_]](implicit F : Monad[F]) = { new Monad[OptionT[F, ?]] { def pure[A](a: A): OptionT[F, A] = OptionT(F.pure(Some(a))) def flatMap[A, B](fa: OptionT[F, A])(f: A => OptionT[F, B]): OptionT[F, B] = OptionT { F.flatMap(fa.value) { case None => F.pure(None) case Some(a) => f(a).value } } } }
This sort of construction is called a monad transformer. Cats already provides
a monad transformer for Option
called OptionT
.
flatMap
is often considered to be the core function of Monad
, and cats
follows this tradition by providing implementations of flatten
and map
derived from flatMap
and pure
.
flatMap
is often considered to be the core function of Monad
, and cats
follows this tradition by providing implementations of flatten
and map
derived from flatMap
and pure
.
implicit val listMonad = new Monad[List] { def flatMap[A, B](fa: List[A])(f: A => List[B]): List[B] = fa.flatMap(f) def pure[A](a: A): List[A] = List(a) }
Part of the reason for this is that name flatMap
has special significance in
scala, as for-comprehensions rely on this method to chain together operations
in a monadic context.
Monad
provides the ability to choose later operations in a sequence based on
the results of earlier ones.
Monad
provides the ability to choose later operations in a sequence based on
the results of earlier ones. This is embodied in ifM
, which lifts an if
statement into the monadic context.
If Applicative
is already present and flatten
is well-behaved,
extending the Applicative
to a Monad
is trivial.
If Applicative
is already present and flatten
is well-behaved,
extending the Applicative
to a Monad
is trivial. To provide evidence
that a type belongs in the Monad
type class, cats' implementation
requires us to provide an implementation of pure
(which can be reused
from Applicative
) and flatMap
.
We can use flatten
to define flatMap
: flatMap
is just map
followed by flatten
. Conversely, flatten
is just flatMap
using
the identity function x => x
(i.e. flatMap(_)(x => x)
).
import cats._ implicit def optionMonad(implicit app: Applicative[Option]) = new Monad[Option] { // Define flatMap using Option's flatten method override def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = app.map(fa)(f).flatten // Reuse this definition from Applicative. override def pure[A](a: A): Option[A] = app.pure(a) }
Cats already provides a Monad
instance of Option
.
This method has been deprecated in favor of macro assertion and will be removed in a future version of ScalaTest. If you need this, please copy the source code into your own trait instead.
This method has been deprecated in favor of macro assertion and will be removed in a future version of ScalaTest. If you need this, please copy the source code into your own trait instead.
This method has been deprecated in favor of macro assumption and will be removed in a future version of ScalaTest. If you need this, please copy the source code into your own trait instead.
This method has been deprecated in favor of macro assumption and will be removed in a future version of ScalaTest. If you need this, please copy the source code into your own trait instead.
Please use 'an [Exception] should be thrownBy { ... }' syntax instead
This expect method has been deprecated. Please replace all invocations of expect with an identical invocation of assertResult instead.
This expect method has been deprecated. Please replace all invocations of expect with an identical invocation of assertResult instead.
This expectResult method has been deprecated. Please replace all invocations of expectResult with an identical invocation of assertResult instead.
This expectResult method has been deprecated. Please replace all invocations of expectResult with an identical invocation of assertResult instead.
Monad
extends theApplicative
type class with a new functionflatten
. Flatten takes a value in a nested context (eg.F[F[A]]
where F is the context) and "joins" the contexts together so that we have a single context (ie.F[A]
).