Looks good. Translating this flow back to code gives us very generic function that can be used to implement all the buisness logic we have:

Code

We can customize its behavior by plugging in various functions. For example:

Starting production seems to be a little harder because of multiple arguments involved. But when you think about it, each function with multiple arguments can be changed to a Function1 using case class encapsulation:

It is much easier to add new functionality now. Because the business logic is abstracted out to a flow, the only place that needs to be changed is the flow itself. Let’s review our goal: production lot cannot be modified if its status has been set to done. It’s trivial to introduce it now, we have already seen it in the previous diagram.

Although we have improved internals of existing code a bit there is still much bigger problem to tackle on the outside: to eliminate exceptions.

Even Yoda recommends not to use exception handling for control flow. “Do or do not, there is no try”

Replacing exceptions with Either

Representing various outcomes of a computation with Either forms a powerful pattern. It makes error handling the part of normal control flow and allows for a fully type-safe and functional code in the presence of errors.

Let’s revisit all the places in our code base where exception may be thrown and rewrite them using Either. We’ll represent error cases as subtypes of the new Error class which encode what went wrong in the type and carry some additional information.

Code

But we immediately notice a problem — our shiny arrow stops compiling! If you tried to fix it, it’d become clear that there is no easy way to compose these functions! Every function would have to unpack a value from Either and pack result back into a new instance of Either . Resulting code would be horrible mess with a lot of boilerplate. Things look bleak. Seems we’re in worse shape than before…

Fear not. As we said arrows are a general interface to computation. This implies that many different computation types can be expressed using arrows. Do not forget that arrow does not impose restrictions on underlying type as long you can come up with implementations of abstract operations that arrow typeclass needs ie. first / second and compose . While ordinary A => B functions are clearly not sufficient to express our new idea, there exists another abstraction designed to do that. It is called Kleisli to honor Swiss mathematician who studied properties of categories associated to monads. Going back to our Scala domain Kleisli represents monadiccomputations i.e. functions of type A => M[B] . We’ll be able to implement arrow on Kleisli , creating so called Kleisli arrows ie. arrows that can compose functions of type A => M[B] as long as M is a monad.

What’s a monad?

Monad is bread and butter of functional programming. I’m not going to explain the concept in this blog post. It’d probably take quite a few (posts — pun intended) to just skim through theory and practice of monads. For our purposes it suffices to know that monad is a container with two operations: bind and return (sometimes called unit but we’ll be calling it point to keep things faimilar for Scalaz people). These operations have the following semantics (from wiki):

The return operation takes a value from a plain type and puts it into a monadic container using the constructor, creating a monadic value.

The bind operation takes as its arguments a monadic value and a function from a plain type to a monadic value, and returns a new monadic value.

Many types you’ve probably used thousands of times can be treated as monads. For instance, a famous example of a Monad is List with return creating one element List and bind being Scala’s flatMap . More involved examples include Slick’s Query where return is a Query#apply and bind chains queries together (again, flatMap ).

We’ll also put to use the fact that monad is a kind of functor i.e. it can be mapped over (like a list or a map). So we’ll add another operation to monad interface, called fmap that will give us ability to map over monadic values.

Putting this together, we’ll be representing monads as members of the following typeclass:

Code

Because we’ll be using bind quite a lot let’s make it a symbolic operator. I’ve chosen >>= to adhere to a Haskell tradition.

Is Either a monad?

Well, no it is not. But we won’t let that stop us :-)

First of all, monad is of kind * -> * while Either ‘s kind is * -> * -> * (that’s fancy way of saying that Monad type constructor takes one type parameter while Either takes two). Then, you cannot compose Either without knowing whether it is Right or Left . Sometimes people say that Either lacks bias e.g. had it been right biased it would have been composable just like Option is by sticking to the RightProjection and bailing out on LeftProjection .

But we can easily form it into Monad ourselves. We just have to use one of the most loathed Scala features called type lambdas to curry Either type constructor into * -> * . Later on I’m going to show how to make syntax easier on the eyes but for now let’s stick to standard ways:

Code

In this code we fixed bias and type kind in one go. (Sorry for the Greek letters, I have some weakness for them :-) ). In case you didn’t come across type lambdas syntax before, { type λ[β] = Either[L, β] })#λ means: produce a new (anonymous) type with one hole but equivalent to Either[L, β] where L has been fixed. We’ll be using type lambdas quite a lot throughout this series, so please make sure that you understand this strange syntax. Implementation-wise we bind and map only with right projection thus giving Either right bias we so much needed.

Implement Kleisli and Kleisli arrow

Kleisli type as such is just a wrapper over functions of type A => M[B] . Still, we can put a few operations into it, provided that M[_] is an instance of monad eg. andThen and compose variants that we’ll reuse for arrow composition and map function that we’ll use later.

Code

To get back an ordinary function from Kleisli without much hassle I have added an implicit conversion from Kleisli to function type.

The most important building block of Kleisli composition is this piece of code

Kleisli((a: A) => this(a) >>= k.run) . It gives a recipe of monadic composition: get a monad instance and use this monad’s bind with a function that takes value out of monad and produces new monad. Monad takes care of plumbing. If you look closer that’s exactly what we missed when we tried to use Either with arrows – now instead of implementing it by hand and cluttering our code we extracted this boilerplate into monads and arrows. What is left to be done is to implement Arrow made with Kleisli s. That’s easy enough:

Code

Let’s explain a few details. Once again we needed to use type lambdas to trick Scala into thinking that Kleisli is a right type parameter to Arrow trait. We abstracted out monad leaving only arrow’s input and output. All the methods rely on point to create a new monad instance and bind to push a value out of a monad into another one. Thus, you can’t have Kleisli arrow without Monad, these two need to go together. To implement compose we just used andThen syntax from Kleisli . We also have to tell the compiler how to convert our new arrow to ArrowOps to use convenient syntax:

This looks terrible, but well, what can we do. Previous definition was not adequate because it insisted on type of F being of * -> * ->* while Kleisli has got (* -> *) -> * -> * -> * kind.

Now we are finally able to incorporate error handling into our flow

Implement error handling using Kleisli arrows

Let’s go back to the drawing board. The flow can be much simplified because we won’t be relying on side effects to propagate errors. What’s more, handling of errors will be responsibility of an Either monad, so we do not have to write any code or alter the logic to take care of this. Thus, we can enjoy smooth linear flow. A railway, if you will. Hence the term railway oriented programming, coined by Scott Wlashin.

Red lines represent ‘error handling track’. Their presence is caused by how we implemented bind in the Either monad i.e. binding is right biased. When Left value is encountered, it breaks the flow. Bold blue lines represent Kleisli composition, they combine monadic values together by unpacking them and feeding the next computation. One problem you might have noticed is the copying function represented by the dotted rectangle. It is not monadic and as such cannot participate in the normal flow.

Integrating non-monadic functions

When composing monadic functions we obtain a monad instance M[B] from M[A] by means of A => M[B] , a binding function. Non-monadic functions, on the other hand, are of form A => B . That’s precisely the difference between flatMap and map , and that’s the very reason we implemented map function on Kleisli . Mapping lets us obtain a new monad instance by means of a function that does not have to do anything with monads. To recap – if you have a need to integrate non-monaidc functions into a pipeline, use map .

Back to the code. Now, our business logic can handle errors and normal flow with ease:

Code

We can cross out another requirement: exceptions are gone.

On the other hand we came across some difficulties. First of all, passing the environment had been quite a hassle. Environment represented additional data that logic needed to operate on, and it didn’t adhere to our monadic model. That forced us to rewrite the code a bit, leveraging the fact that what we’ve got after all is functions, and functions can be partially applied and curried. That’s how we were able to completely eliminate env parameter from the equation.

Second, you need type alias to use functions returning Either as Kleisli

no type parameters for method apply: (run: A => M[B])org.virtuslab.blog.kleisli.Kleisli[M,A,B] exist so that it can be applied to arguments (org.virtuslab.blog.kleisli.ProductionLot =>

Either[org.virtuslab.blog.kleisli.Error,org.virtuslab.blog.kleisli.ProductionLot])

[error] — because —

[error] argument expression’s type is not compatible with formal parameter type;

[error] found : org.virtuslab.blog.kleisli.ProductionLot =>

Either[org.virtuslab.blog.kleisli.Error,org.virtuslab.blog.kleisli.ProductionLot]

[error] required: ?A => ?M[?B]

[error] Kleisli { verify(_, env) } >>>

You may be tempted to employ type lambdas to get rid of alias e.g.

but, aside readability woes, it is path to nowhere because of one of the most famous Scala compiler bugs: SI-2712. Compiler complains that:

value >>> is not a member of org.virtuslab.blog.kleisli.Kleisli[[R]scala.util.Either[org.virtuslab.blog.kleisli.Error,R],Long,org.virtuslab.blog. kleisli.ProductionLot]

which is because of:

ToArrowOpsFromKleisliLike is not a valid implicit value for (=>

org.virtuslab.blog.kleisli.Kleisli[[R]scala.util.Either[org.virtuslab.blog.kleisli.Error,R],Long,org.virtuslab.blog. kleisli.ProductionLot]) => ?{def >>>: ?} because:

[info] no type parameters for method ToArrowOpsFromKleisliLike: (v: F[G,A,B])(implicit arr: org.virtuslab.blog. kleisli.Arrow[[β, γ]F[G,β,γ]])org.virtuslab.blog.kleisli.ArrowOps[[β, γ]F[G,β,γ],A,B] exist so that it can be applied to arguments

(org.virtuslab.blog.kleisli.Kleisli[[R]scala.util.Either[org.virtuslab.blog.kleisli.Error,R],Long,org.virtuslab.blog. kleisli.ProductionLot])

[info] — because —

[info] argument expression’s type is not compatible with formal parameter type;

[info] found :

org.virtuslab.blog.kleisli.Kleisli[[R]scala.util.Either[org.virtuslab.blog.kleisli.Error,R],Long,org.virtuslab.blog. kleisli.ProductionLot]

[info] required: ?F[?G, ?A, ?B]

You might utter a cry of disbelief when you see that. After all, it is quite obvious that the following unification makes formal and actual types fit together: {F[_, _, _] / Kleisli, G[_] / [R]scala.util.Either[org.virtuslab.blog.kleisli.Error,R], A / Long, B/ ProductionLot } . Well, your intuition is right, but compiler cannot perform partial polymorphic type inference. Quoting Paul Philips:

Type lambdas are cool and all, but not a single line of the compiler was ever written with them in mind. They’re just not going to work right: the relevant code is not robust.

If you think you can outsmart it introducing exact implicit conversion, compiler will retaliate with not finding implicit arrow instance needed for the conversion.

Instead of tilting with windmills it’s better to refactor it slightly to guide type inference:

Code

Summary

In this part we’ve been able to achieve quite a lot. Starting from uncomposable, imperative code with side effects, we’ve slowly paved our way to a proper functional

code with error handling. It’s as if we’ve built ourselves a little language to help us express various aspects of control flow normally implemented in imperative manner, without compromising on composability. In the next part we’ll extend this example by implementing more requirements that you’d often find in coding business logic eg. logging (side-effects). I’ll also eliminate ugly looking type lambdas. Further down the road we’ll look at the envparam once again and devise a way to handle it more cleanly, thus giving birth to arrow transformers. Stay tuned.