Here we have two possible paths of execution (marked red and blue) based on data held in an Either instance passed as input.

left(f) feeds Left input through its argument arrow, leaving the other part unchanged. right(f) mirrors left . Thinking in terms of Scala library, these operators are maps on, respectively, Left and Right projections.

Multiplex(+++) simply combines both left and right into a single operation. It applies f if input is a Left or g if it is a Right

Fanin(|||) is +++ which merges the output. Think Scala’s Either.fold .

Implementation is straightforward:

Code

… and additional symbolic ops:

What’s left to be done is to implement Choice for arrow instances that support it. Both function and Kleisli do, but to keep it simple we’ll do that only for functions (after all, we’re using it for logging only):

Code

Of course, it would have sufficed to implement just left and right but, as we observed, for functions it is perfectly possible to write simpler code, based on Scala standard library. Only multiplex is not equivalent to any method. It comes as no surprise because, as was said before, Either lacks bias, forcing us to choose explicitly which side we want to operate on. If it had been biased, +++ would have been map .

The stage is set to add logging to ProductionLotService . Let’s extend productionLotArrow to accept custom logging function of type (ProductionLot, Env) => Unit (after all, each caller wants a different message to be logged). Additionally, arrow implementation will log the outcome of flow (either success or error) by itself. Putting it together we get:

Code

With a little help of -| operator, logging is painlessly stitched to where it belongs.

Curious reader might be asking, why is there a run called? ( run extracts a function from Kleisli and there is an implicit conversion for that). Well, the short answer is that it’s because implicit conversions in Scala aren’t chained. Now, the long answer: to deduce that the correct call is actually -| coming from function arrow (not the one from Kleisli arrow), compiler would have had to construct chain of conversions leading from Kleisli through Function1 (via run method) to ArrowOps(FunctionArrow) . Instead it sees that -| can be obtained by one step conversion Kleisli -> ArrowOps(KleisliArrow) , and sticks to that. But KleisliArrow requires Long => Unit action, while what we’ve got is a conditional Either[Error, Long] => Unit . So we have to manually unpack function from Kleisli .

After all this we can freely enhance different use cases with logging:

Mixing monads

I promised to show how to face the situation when functions that you want to build pipeline from can’t agree on what monad they use. Let’s imagine that save method wants to return Try instead of Either :

Obviously we also need to state that Try is actually a monad (there is some controversy about that, but I won’t delve into this matter):

Code

There is no one-size-fits-all answer, I believe, but I’ll show you two possible ways of solving this awkwardness.

Lift

The crucial observation here is that if you have a function A => B and a functor F[A] , you can easily transform the function into a function of F[A] => F[B] type. We’ve already seen that in action when we integrated non-monadic functions with Kleisli . It’s exactly what map does. If you recall, map ‘s signature on Kleisli[M, A, B] (a function A => M[B] ) is:

map composes B => C with A => M[B] to get A => M[C] . In other words it turns a function of type B => C into a M[B] => M[C] function.

This is possible with all functors, and, as you probably remember from part one, every monad is a functor.

Now, we can pretend that function A => Try[B] is kind of non-monadic from the perspective of Either monad and write this as follows:

Or, we can name this operation explicitly by adding liftM method to Kleisli class:

Code

which turns arrow definition into:

This approach works fine, but it adds a lot of burden when you want to do anything with the result. The whole arrow definition after these changes looks like this:

Code

The bad thing is that type of the constructed function changes from nice Either[Error, Long] into less-than-perfect Either[Error, Try[Long]] . You can see how it affected logging. logSuccess needs to accomodate the additional layer of types and be rewritten from Long => Unit into Try[Long] => Unit and that, in turn, forces us to pattern-match on input. It’s not the end of the world though. What are the other options?

Natural transformation

There are tons of material treating the subtleties of natural transformations, ranging from deep theoretical explanations to more practical ones.

The definition from Wikipedia states simply that:

a natural transformation provides a way of transforming one functor into another while respecting the internal structure (i.e. the composition of morphisms)

We’ll not be doing anything fancy though. For our purposes a natural transformation is just a generalization of map ( A => B ) that works on higher-order types ( M[_] => N[_] ).

Code

The fancy ~> type used in transform behaves exactly like a generalized map that can transform one monad into another, irrespective of type of a value the monad carries inside. BTW, what a fine example of higher-order polymorphism.

And transform is very simple to use:

Code

One can say that save ‘s just got back on track :-)

The end

All right, that’s all folks. Stay tuned for the last part of series. Hope you enjoyed it so far.