What is functor bias? - scala

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.

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.

Where is that functor which free monad is supposed to be based on

I'm trying to comprehend the idea of free monad, and I'm stumped on the first sentence of cats's docs stating that
A free monad is a construction which allows you to build a monad from
any Functor
My confusion is mainly related to the fact that there is no any functor used\created in the process of "freeing" ADT for KVStoreA. There is no implementation of functor for ADT or something like that. However, documentation for Free[S[_],A] says that S must me a functor:
A free operational monad for some functor S.
Where is that functor that free monad is supposed to be based on?
Thing is, Free monad can be used in a few different ways. In order to use one of them you assume that you have some functor S[_], it will have some Functor[S] defined and you will lift that S[*] to Free[S, *] by allowing some sort of extension to the original S:
Free[S, A] = S[A] or A
This is not valid Scala! They way it is actually implemented is using ADT. This only serves as an explanation of the idea.
This way if you have S[A] and you map it with f: A => B, you would use Functor[S] and receive S[B]. But if you flatMap it with f: A => Free[S, B]... you would still be able to calculate that using Functor[S] and receive S[Free[S, B]]. That's what this code would be be underneath. Remembering that Free[S, A] = S[A] or A you could see that this would turn into S[S[S[...]]] and it could go infinitely nested if not for or A part of Free[S, A] which would let us stop at some point.
Of course we don't calculate it all at once, Free usually uses trampoline to calculate only one thing at a time, so we aren't gonna end with tons of nesting at once.
sealed abstract class Free[S[_], A] extends Product with Serializable {
// ...
}
object Free extends FreeInstances {
/**
* Return from the computation with the given value.
*/
final private[free] case class Pure[S[_], A](a: A) extends Free[S, A]
/** Suspend the computation with the given suspension. */
final private[free] case class Suspend[S[_], A](a: S[A]) extends Free[S, A]
/** Call a subroutine and continue with the given function. */
final private[free] case class FlatMapped[S[_], B, C](c: Free[S, C], f: C => Free[S, B]) extends Free[S, B]
...
}
This trampoline representation implements the same idea as S[A] or A but it allows running computations one step at a time. It also shows that Free[S, *] is S[*] algebra extended by pure and flatMap operations (that assume nothing about S), which justifies calling Free a free algebra.
Actually, until we decide to run the computations we only have lazily evaluated data structure. One way of running it is to call free.run that you have defined for Free in cats - it will use trampoline to evaluate each of this nestings, one at a time, but then it will use Comonad[S] to extract the value - as a result we will get rid of nestings as we go. Comonad[S] is also Functor[S] which is why we don't have to provide it separately to do all these maps.
But that is one way of running things. Another way of running things is just assuming that we are recording the map, flatMap and pure operations using Free. For that we don't have to have Functor[S] at all. We might decide to run things using Comonad[S], but we might also decide something else. What if we translated S[_] to some M[_], but that we knew that this M[_] had a Monad[M]? In this case, we wouldn't have to use Functor[S] at all! We would run translation S ~> M, then, map or flatMap on it, and the S inside of it would be translated using the same S ~> M mechanism. This is what foldMap does - it requires us to provide a natural transformation S ~> M and instance of Monad[M] and Functor[S] is completely unnecessary. While conceptually we can still consider that S as a functor we don't need to rely on any of functors properties, not in the form of Functor[S].
So to finally answer your question - with Free when we are still at the stage of "recording operations" we don't have to assume that S is a functor, so we don't need Functor[S]. When we want to interpret Free[S, A] into something - this is where functor might be actually needed, e.g. if we want to run Free[S, A] into A. But for some interpretations like e.g. foldMap (which is IMHO one of the most popular ones) this is not needed because we treat S as a plain data.

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?

In Scala type parameters, what do ->> and ->>> mean?

Heiko Seeberger wrote a great blog post on category theory here:
https://hseeberger.wordpress.com/2010/11/25/introduction-to-category-theory-in-scala/
In it, he defines a GenericFunctor like so:
trait GenericFunctor[->>[_, _], ->>>[_, _], F[_]] {
def fmap[A, B](f: A ->> B): F[A] ->>> F[B]
}
I did not have any luck finding documentation references to the ->> and ->>> symbols in documentation. Could someone please explain what they are doing?
The symbols themselves don't mean anything. They are arbitrary names Heiko picked:
> class Foo[A, B]
defined class Foo
> class Foo[M1[_], M2[_]]
defined class Foo
> class GenericFunctor[->>[_, _], ->>>[_, _], F[_]]
defined class GenericFunctor
They are parts of type parameters that they themselves are type constructors (higher-kinded types if you want to sound fancy).
Type applications can be written infix, so A ->> B is same as ->>[A, B].
As per what's going on... Heiko says
Looking at the ingredients, we find all that we need: Types A and B are mapped to types F[A] and F[B] and maps A ->> B are mapped to maps F[A] ->>> F[B].
Since we are talking category theory, we want to avoid the term function because that's implementation specific, but we want to describe something kind of like a function. Something-like-a-function in their lingo is an arrow. We need two of them since we don't want to assume the incoming and outgoing arrows to be the same. These two arrows are represented by ->> and ->>>. F[_] is a container like List and Option. I think..
So fmap (aka map method in Scala) takes an arrow of values and returns another arrow of containers. Except unlike map method, fmap returns an arrow that takes a container.
A specific application of the GenericFunctor using Function for both arrows is Functor. And specific application of Functor that uses List for the container is ListFunctor.
object ListFunctor extends Functor[List] {
def fmap[A, B](f: A => B): List[A] => List[B] = as => as map f
}
So that's taking a function from A to B, and returning a function from List[A] to List[B], calling map internally.
A clue is that they are within square brackets in the trait definition: they are just arbitrary symbols that have been picked by the blog author, just as [T] is often chosen for generic classes, traits, and methods. These here just happen to be higher-kinded types (i.e. parameters with parameters).
The arrow-like name was chosen because, as he says,
"A ->> B is just another way to write ->>[A, B], which nicely reflects
the fact that we are talking about maps here."
Answer copied from my answer to a duplicate question on request:
It's a higher-kinded type, described nicely in this introduction and in this research paper.
The reason you might find it confusing is that ->> is the name for the higher-kinded type -- it might have as well been called Arrow instead.