How is Kleisli a monad Transformer? - scala

Some definition of Monad Transformers in cats.
EitherT[F[_], A, B] is a lightweight wrapper for F[Either[A, B]] that
makes it easy to compose Eithers and Fs together. To use EitherT,
values of Either, F, A, and B are first converted into EitherT, and
the resulting EitherT values are then composed using combinators.
OptionT[F[_], A] is a light wrapper on an F[Option[A]]. Speaking
technically, it is a monad transformer for Option, but you don’t need
to know what that means for it to be useful. OptionT can be more
convenient to work with than using F[Option[A]] directly.
I understand the concept, even saw some interesting talk about it: Monad transformers down to earth by Gabriele Petronella
I understand the Reader Monad, and how Kleisli is just a generalization.
What i do not understand is the statement bellow, that says that it is a monad transformer. What are we stacking exactly ? I don't see 2 monad being stacked here ....
Kleisli can be viewed as the monad transformer for functions. Recall
that at its essence, Kleisli[F, A, B] is just a function A => F[B],
with niceties to make working with the value we actually care about,
the B, easy. Kleisli allows us to take the effects of functions and
have them play nice with the effects of any other F[_].
Any thoughts ?

Monad transformer EitherT[F[_], A, B] (a wrapper for F[Either[A, B]]) appears when we consider composition of two monads: F (outer monad) and Either[A, ?] (inner monad).
Monad transformer OptionT[F[_], A] (a wrapper for F[Option[A]]) appears when we consider composition of two monads: F (outer monad) and Option (inner monad).
Monad transformer Kleisli[F, A, B] (a wrapper for A => F[B]) appears when we consider composition of two monads: A => ? (outer monad) and F (inner monad).

Related

Why Semigroupal for types that have Monad instances don't combine?

I am trying wrap my head around Semigroupals in Cats. Following are statements from "Scala with Cats" by Underscore.
cats.Semigroupal is a type class that allows us to combine contexts
trait Semigroupal[F[_]] {
def product[A, B](fa: F[A], fb: F[B]): F[(A, B)]
}
The parameters fa and fb are independent of one another: we can compute them in either order before passing them to product. This is in contrast to flatMap, which imposes a strict order on its parameters.
So basically, we should be able to combine two Either contexts as well but that doesn't seem to work:
import cats.instances.either._
type ErrorOr[A] = Either[Vector[String], A]
Semigroupal[ErrorOr].product(Left(Vector("Error 1")), Left(Vector("Error 2")))
// res3: ErrorOr[Tuple2[Nothing, Nothing]] = Left(Vector("Error 1"))
If the USP of semigroupal is to eagerly execute independent operations, both eithers must be evaluated before being passed to product and yet we can't have a combined result.
We might expect product applied to Either to accumulate errors instead of fail fast. Again, perhaps surprisingly, we find that product implements the same fail‐fast behaviour as flatMap.
Isn't it contrary to the original premise of having an alternative approach to be able to combine any contexts of same type?
To ensure consistent semantics, Cats’ Monad (which extends Semigroupal) provides a standard definition of product in terms of map and flatMap.
Why implement product in terms of map and flatMap? What semantics are being referred to here?
So why bother with Semigroupal at all? The answer is that we can create useful data types that have instances of Semigroupal (and Applicative) but not Monad. This frees us to implement product in different ways.
What does this even mean?
Unfortunately, the book doesn't covers these premises in detail! Neither can I find resources online. Could anyone please explain this? TIA.
So basically, we should be able to combine two Either contexts as well but that doesn't seem to work:
It worked, as you can see the result is a valid result, it type checks.
Semigrupal just implies that given an F[A] and a F[B] it produces an F[(A, B)] it doesn't imply that it would be able to evaluate both independently or not; it may, but it may as well not. Contrary to Monad which does imply that it needs to evaluate F[A] before because to evaluate F[B] it needs the A
Isn't it contrary to the original premise of having an alternative approach to be able to combine any contexts of same type?
Is not really a different approach since Monad[F] <: Semigroupal[F], you can always call product on any Monad. Implementing a function in terms of Semigroupal just means that it is open to more types, but it doesn't change the behavior of each type.
Why implement product in terms of map and flatMap? What semantics are being referred to here?
TL;DR; consistency:
// https://github.com/typelevel/cats/blob/54b3c2a06ff4b31f3c5f84692b1a8a3fbe5ad310/laws/src/main/scala/cats/laws/FlatMapLaws.scala#L18
def flatMapConsistentApply[A, B](fa: F[A], fab: F[A => B]): IsEq[F[B]] =
fab.ap(fa) <-> fab.flatMap(f => fa.map(f))
The above laws implies that for any F[A] and for any F[A => B] as long as there exists a Monad (actually FlatMap) for F then, fab.ap(fa) is the same as fab.flatMap(f => fa.map(f))
Now, why? Multiple reasons:
The most common one is the principle of least surprise, if I have a bunch of eithers and I pass them to a generic function, no matter if it requires Monad or Applicative I expect it to fail fast, since that is the behavior of Either.
Liskov, suppose I have two functions f and g, f expects an Applicative and g a Monad, if g calls f under the hood I would expect calling both to return the same result.
Any Monad must be an Applicative, however an accumulating Applicative version of Either requires a Semigroup for the Left, whereas, the Monad instance doesn't require that.
What does this even mean?
It means that we may define another type (for example, Validated) that would only satisfy the Applicative laws but not the Monad laws, as such it can implement an accumulating version of ap
Bonus, since having this situation of having a type that is a Monad but could implement an Applicative that doesn't require sequencing, is so common. The cats maintainers created Parallel to represent that.
So instead of converting your Eithers into Validateds to combine them using mapN you can just use parMapN directly on the Eithers.

What is functor bias?

Following up from C++ Functors - and their uses, I have come across 'right biased functor' and 'left biased functor'. I have tried to do some research on my own, but I am still failing to understand the difference between both, and what functor bias even is.
Can someone please give an overview of what functor bias is, the difference between right bias and left bias, along with any examples of how this would be useful? It would be great if Scala could be used for the examples.
Functor in scala isn't quite the same thing as what they call that in C++. It is a category with an operation like
def map[A, B](fa: F[A])(f: A => B): F[B]
that turns F[A] into F[B] given a transformer from A to B.
For example, an Option is a functor, that applies the transformation to the inner value when it is defined. A List is a functor, that applies the transformer to each element, etc.
Now, consider, something like Either[A, B]. Suppose, we wanted to define a functor for that. It takes two type parameters, but Functor only has one, so we have to choose on which the Functor will operate. It is common to use Either in a way, where Right is the default case, and Left is an exception (an error condition). So, it is natural, to consider it right-biased:
def eitherFunctor[T] = new Functor[Either[T, ?]] {
def map(fa: Either[T, A])(f: A => B): Either[T, B] = fa match {
case Right(a) => Right(f(a))
case Left(t) => Left(t)
}
}
This works kinda like Option.map: when Either is a Right, it applies the transformer, otherwise, just returns the Left untouched. Thus, it can be said that Either is a right-biased functor, because it only operates on its right side.

Why do monads not compose in scala

Why do monads not compose when a Monad is an Applicative and an Applicative is a Functor. You see this inheritance chain in many articles on the web ( Which i have gone through ). But when Functors and Applicatives compose why do Monads break this ?
Can someone provide a simple example in scala which demonstrates this issue ? I know this is asked a lot but kind of hard to understand without a simple example.
First, let's start with a simple problem. Let's say, we need to get a sum of two integers, each wrapped in both Future and Option. Let's take cats library in order to resemble Haskell’s standard library definitions with Scala-syntax.
If we use monad approach (aka flatMap), we need:
both Future and Option should have Monad instances defined over them
we also need monadic transformer OptionT which will work only for Option (precisely F[Option[T]])
So, here is the code (let's forget about for-comprehension and lifting to make it simpler):
val fa = OptionT[Future, Int](Future(Some(1)))
val fb = OptionT[Future, Int](Future(Some(2)))
fa.flatMap(a => fb.map(b => a + b)) //note that a and b are already Int's not Future's
if you look at OptionT.flatMap sources:
def flatMap[B](f: A => OptionT[F, B])(implicit F: Monad[F]): OptionT[F, B] =
flatMapF(a => f(a).value)
def flatMapF[B](f: A => F[Option[B]])(implicit F: Monad[F]): OptionT[F, B] =
OptionT(F.flatMap(value)(_.fold(F.pure[Option[B]](None))(f)))
You'll notice that the code is pretty specific to Option's internal logic and structure (fold, None). Same problem for EitherT, StateT etc.
Important thing here is that there is no FutureT defined in cats, so you can compose Future[Option[T]], but can't do that with Option[Future[T]] (later I'll show that this problem is even more generic).
On the other hand, if you choose composition using Applicative, you'll have to meet only one requirement:
both Future and Option should have Applicative instances defined over them
You don't need any special transformers for Option, basically cats library provides Nested class that works for any Applicative (let's forget about applicative builder's sugar to simplify understanding):
val fa = Nested[Future, Option, Int](Future(Some(1)))
val fb = Nested[Future, Option, Int](Future(Some(1)))
fa.map(x => (y: Int) => y + x).ap(fb)
Let's swap Option and Future:
val fa = Nested[Option, Future, Int](Some(Future(1)))
val fb = Nested[Option, Future, Int](Some(Future(1)))
fa.map(x => (y: Int) => y + x).ap(fb)
Works!
So yes Monad is Applicative, Option[Future[T]] is still a monad (on Future[T] but not on T itself) but it allows you to operate only with Future[T] not T. In order to "merge" Option with Future layers - you have to define monadic transformer FutureT, in order to merge Future with Option - you have to define OptionT. And, OptionT is defined in cats/scalaz, but not FutureT.
In general (from here):
Unfortunately, our real goal, composition of monads, is rather more
difficult. .. In fact, we can actually prove that, in a certain sense,
there is no way to construct a join function with the type above using
only the operations of the two monads (see the appendix for an outline
of the proof). It follows that the only way that we might hope to form
a composition is if there are some additional constructions linking
the two component
And this composition is not even necessary commutative (swappable) as I demonstrated for Option and Future.
As an exercise, you can try to define FutureT's flatMap:
def flatMapF[B](f: A => F[Future[B]])(implicit F: Monad[F]): FutureT[F, B] =
FutureT(F.flatMap(value){ x: Future[A] =>
val r: Future[F[Future[B]] = x.map(f)
//you have to return F[Future[B]] here using only f and F.pure,
//where F can be List, Option whatever
})
basically the problem with such implementation is that you have to "extract" value from r which is impossible here, assuming you can't extract value from Future (there is no comonad defined on it) at least in a "non-blocking" context (like ScalaJs). This basically means that you can't "swap" Future and F, like Future[F[Future[B]] => F[Future[Future[B]. The latter is a natural transformation (morphism between functors), so that explains the first comment on this general answer:
you can compose monads if you can provide a natural transformation swap : N M a -> M N a
Applicatives however don't have such problems - you can easily compose them, but keep in mind that result of composition of two Applicatives may not be a monad (but will always be an applicative). Nested[Future, Option, T] is not a monad on T, regardless that both Option and Future are monads on T. Putting in simple words Nested as a class doesn't have flatMap.
It would be also helpful to read:
http://typelevel.org/cats/tut/applicative.html
http://typelevel.org/cats/tut/apply.html
http://typelevel.org/cats/tut/monad.html
http://typelevel.org/cats/tut/optiont.html
Putting it all together (F and G are monads)
F[G[T]] is a monad on G[T], but not on T
G_TRANSFORMER[F, T] required in order to get a monad on T from F[G[T]].
there is no MEGA_TRANSFORMER[G, F, T] as such transformer can't be build on top of monad - it requires additional operations defined on G (it seems like comonad on G should be enough)
every monad (including G and F) is applicative, but not every applicative is a monad
in theory F[G[T]] is an applicative over both G[T] and T. However scala requires to create NESTED[F, G, T] in order to get composed applicative on T (which is implemented in cats library).
NESTED[F, G, T] is applicative, but not a monad
That means you can compose Future x Option (aka Option[Future[T]]) to one single monad (coz OptionT exists), but you can't compose Option x Future (aka Future[Option[T]]) without knowing that Future is something else besides being a monad (even though they’re inherently applicative functors - applicative is not enough to neither build a monad nor monad transformer on it) . Basically:
OptionT can be seen as non-commutative binary operator defined as OptionT: Monad[Option] x Monad[F] -> OptionT[F, T]; for all Monad[F], T; for some F[T]. Or in general: Merge: Monad[G] x Monad[F] -> Monad[Merge]; for all T, Monad[F]; but only for **some of Monad[G]**, some F[T], G[T];
you can compose any two applicatives into one single applicative Nested: Applicative[F] x Applicative[G] -> Nested[F, G]; for all Applicative[F], Applicative[G], T; for some F[T], G[T],
but you can compose any two monads (inherently functors) only into one applicative (but not into monad).
Tony Morris gave a talk on monad transformers that explains this precise issue very well.
http://tonymorris.github.io/blog/posts/monad-transformers/
He uses haskell, but the examples are easily translatable to scala.

How to specify that abstract types must implement certain typeclasses in scalaz?

I want to write a function which simply binds two monads together, without fixing in advance the exact type of the monads (Lists, State monads, etc.). It seems to me that this kind of genericity is the reason why typeclasses are so powerful, and that I should be able to do it with Scalaz. Here is what I have in mind:
def f[F[_], A](m1: F[A], m2: F[A]): F[(A,A)] =
m1 >>= { a: A => m2.map{ b: A => (a,b) }}
How do specify that F[_] must implement the Monad typeclass so that I can use >>= in my function? Writing F[_] <: Monad doesn't seem to be the right approach since the types State, List, etc... which are monads don't extend the Monad trait.
It sounds like context bounds are exactly what you're looking for. f[F[_] : Monad... See What are Scala context and view bounds?

Is it just a coincidence that Kleisli, ReaderT, and Reader are the same in Scalaz

In Scalaz
Kleisli[F, A, B] is a wrapper for A => F[B].
ReaderT[F, A, B] -- reader monad transformer -- is just an alias of Kleisli[F, A, B].
Reader[A, B] monad is a specialization of ReaderT with identity monad Id:
type Reader[A, B] = ReaderT[Id, A, B].
Is it just a coincidence or there are some deeper reasons that Kleisli, ReaderT, and Reader are isomorphic in Scalaz ?
You can think of it as arriving at the same place by two different routes. On one side you start with the reader monad, which is simply a kind of wrapper for functions. Then you realize that you want to integrate this reader functionality into a larger monad with other "effects", so you create a ReaderT monad transformer. At that point it makes sense to implement your original Reader[E, ?] as ReaderT[Id, E, ?].
From the other side, you want a type to represent Kleisli arrows (i.e. functions with a monadic return type). It turns out that this is the same thing as ReaderT, so you just make that an alias.
There's nothing terribly mysterious about the "it turns out" part. It's a little like if you started out with an Addable type class for number-like things, then decide to make it more generic, and eventually end up with a type class that just provides an associative "addition-like" operation. You've reinvented Semigroup! You may still want to keep the Addable name around, though, for historical or pedagogical reasons, or just for convenience.
That's all that's happening with Reader and ReaderT—you don't need these aliases, but they can be convenient, and may help improve the clarity of your code.