Monday, December 27, 2010

A case study of cleaner composition of APIs with the Reader monad

In my earlier post on composable domain models, I wrote about the following DSL that captures the enrichment of a security trade by computing the applicable tax/fees and then the net cash value of the trade. It uses chained composition of scalaz functors .. In this post we are going to improve upon the compositionality, introduce a new computation structure and make our APIs leaner with respect to type signatures ..

scala> trd1 ° forTrade ° taxFees ° enrichWith ° netAmount  
res0: Option[scala.math.BigDecimal] = Some(3307.5000)

Here are the building blocks for the above .. the individual functions and the type definitions for each of them ..

forTrade: Trade => (Trade, Option[List[TaxFeeId]])
taxFees: (Trade, Option[List[TaxFeeId]]) => (Trade, List[(TaxFeeId, BigDecimal)])
enrichWith: (Trade, List[(TaxFeeId, BigDecimal)]) => RichTrade
netAmount: RichTrade => Option[BigDecimal]

and here's the chaining in action with wiring made explicit ..

Note how we explicitly wire the types up so as to make the entire computation composable. Composability is a worthwhile quality to have for your abstractions. However in order for your functions to compose, the types for input and output for each of them must match. In the above example, we need to have forTrade spit out a Trade object along with the list of tax/fee id, in order for it to compose with taxFees.

For an API to be usable, the secret sauce is to make it lean. Never impose any additional burden on to your API's interface that smells of incidental complexity to the user. This is exactly what we are doing in the above composition. Note we are carrying around the Trade argument pipelining it through each of the above functions. In our use case the Trade is a read-only state and needs to be shared amongst all functions to read the information from the object.

Enter the Reader Monad

Refactor the above into the Reader monad. A Reader is meant to be used as an environment (it's also known as the Environment monad) for all the participating components of the computation. What we need to do for this is to set up a monadic structure for our computation. Here are the modified function signatures .. I have changed some of the names for better adaptability with the domain, but you get the idea ..

val forTrade: Trade => Option[List[TaxFeeId]] = //..
val taxFeeCalculate: Trade => List[TaxFeeId] => List[(TaxFeeId, BigDecimal)] = //..
val enrichTradeWith: Trade => List[(TaxFeeId, BigDecimal)] => BigDecimal = //..

Every function takes the Trade but we no longer have to do an explicit chaining by emitting the Trade also as an output. This is where a monad shines. A monad gives you a shared interface to many libraries where you don't need to implement sequencing explicitly within your DSELs.

And here's our DSEL that runs through the sequence of enriching a trade while using the passed in trade as an environment .. (thanks @runarorama for the help with the Reader in scalaz)

val enrich = for {
  taxFeeIds      <- forTrade        // get the tax/fee ids for a trade
  taxFeeValues   <- taxFeeCalculate // calculate tax fee values
  netAmount      <- enrichTradeWith // enrich trade with net amount
yield((taxFeeIds ° taxFeeValues) ° netAmount)

This is a comprehension in Scala which is like the do notation of Haskell. Desugar it as an exercise and explore how flatMap does the sequencing.

Here's what the type of enrich looks like ..

scala> enrich
res1: ( => Option[BigDecimal] = <function1>

enrich is monadic in nature and follows the usual structure of a monad that sequences its operations through bind to give it an imperative look and feel. If any of the above sub-computations fail, the whole computation fails. But show it to a person who knows the domain of security trading - the steps in enrich nicely models the ubiquitous language.

I have the entire DSL in my github repo. You can get the use of enrich here in the test case ..

Monday, December 20, 2010

DSLs In Action is out!

It all started with a mail from Christina of Manning expressing their interest in publishing a book on building parsers in Scala. She mentioned that they have come across a blog post of mine titled External DSLs made easy with Scala Parser Combinators and Marjan Bace (Publisher) would like to talk to me on this possible venture. I still remember that hour long discussion with Marjan that ultimately led to the thoughts of coming out with a book on DSL design.

The ebook of DSLs In Action (buy here)* has been published, the print version is due Dec 24, just in time for Christmas. The final book is sized at 377 pages with 9 chapters and 7 appendices. Before publication the book was reviewed at various levels by an illustrious panel of reviewers. I received lots of feedbacks and suggestions at Manning online Author's Forum. The current incarnation of the book is the result of assimilating all suggestions, feedbacks and critiques aided by the constructive editing process of the Manning crew. Jonas Boner has been kind enough to write the foreword of the book. The result is now a reality for all of you to read, enjoy and review.

Some one asked to me pen down my thoughts on DSLs In Action in one page. Not the literal summary of what it contains, but the impressions of some of the thought snippets that it can potentially induce into the minds of its readers. This post is an attempt towards that.

DSL and polyglotism

A DSL is targeted for a specific domain. Your implementation should be expressive enough to model the ubiquitous language that your domain users use everyday. Hence the practice od DSL driven development has an aura of polyglotism in it. Assuming you have the relevant expertise in your team, target the implementation language that's best suited for developing the syntax of the domain. DSLs In Action considers case studies in Ruby, Groovy, Clojure and Scala and focuses its readers to the implementation patterns of DSLs in each of them.

A DSL as a collaboration medium

The one most standout dimension that DSL driven development adds to a team is an increased emphasis on collaboration. The main value proposition that a DSL brings to table is a better collaboration model between the developers and the domain users. It's no secret that most of today's failed projects attribute their debacle to the huge gap in the developers' understanding of the domain. This mainly results from the lack of communication between the developers and the domain users and also between the different groups of developers. When you have code snippets like the following as part of your domain model ..

import TaxFeeImplicits._
override def calculatedAs(trade: Trade): PartialFunction[TaxFee, BigDecimal] = {
  case TradeTax   => 5.  percent_of trade.principal
  case Commission => 20. percent_of trade.principal
  case Surcharge  => 7.  percent_of trade.principal
  case VAT        => 7.  percent_of trade.principal

you can collaborate very well with your domain experts to verify the correctness of implementation of the business rule for tax calculation on a security trade. DSLs In Action dispels the myth that a DSL will make your domain analysts programmers - it will not. A DSL best serves as the collaboration bridge to discuss business rules' implementation with your analysts.

Importance of the semantic model

A DSL is a thin layer of linguistic abstraction atop a semantic model. I have blogged on this topic some time ago. The semantic model is the set of abstractions on which you grow your DSL syntax. The semantic model can potentially be reused for purposes other than developing your DSL layer - hence it needs to be as loosely coupled as possible with the syntax that your DSL publishes. In DSLs In Action I discuss the concept of a DSL Facade that helps you decouple basic abstractions of the domain model from the language itself.

DSL design is also abstraction design

Throughout DSLs In Action I have highlighted many of the good qualities that a well-designed abstraction needs to have. In fact Appendix A is totally dedicated to discussing the qualities of good abstractions. In almost every chapter I talk about how these qualities (minimalism, distillation, composability and extensibility) apply in every step of your DSL design. In real world when you implement DSLs, you will see that entire DSLs also need to be composed as abstractions. Use a proper language that supports good models of abstraction composition

External and Internal is only one dimension of classifying DSLs

Though broadly I talk about external and internal DSLs, actually there are lots of different implementation patterns even within them. Internal DSLs can be embedded where you emded the domain language within the type system of the host language. Or they can generative where you allow the language runtime to generate code for you, like you do in Ruby or Groovy using dynamic meta-programming. With the Lisp family you can create your own language using macros. Some time back I blogged about all these varying implementation patterns with internal and external DSLs.

Hope you all like DSLs In Action. If you have reached this far in the post, there are chapters 1 and 4 free on Manning site taht would help you get a sneak peak of some of the stuff that I talked about .. Happy Holidays!

* Affiliate Link

Monday, December 13, 2010

Monads, Applicative Functors and sequencing of effects

Monads and applicative functors are both used to model computations - yet it's interesting to note the subtle differences in the way they handle sequencing of effects. Both of them support an applicative style of effectful programming that lets you write code in pointfree style (in Haskell) making your code look so expressive.

Applicative functors are more general than monads and hence have a broader area of application in computation. Haskell does not define monads to be a derivative of applicative functors, possibly for some historical reasons. Scalaz does it and does it correctly and conveniently for you to reduce the number of abstractions that you need to have.

In Haskell we have sequence and sequenceA implemented for monads and applicatives separately ..

-- in Control.Monad
sequence  :: Monad m => [m a] -> m [a]

-- in Data.Traversable
class (Functor t, Foldable t) => Traversable t where
  sequenceA :: Applicative f => t (f a) -> f (t a)

In scalaz we have the following ..

// defined as pimped types on type constructors
def sequence[N[_], B](implicit a: A <:< N[B], t: Traverse[M], n: Applicative[N]): N[M[B]] =
    traverse((z: A) => (z: N[B]))

sequence is defined on applicatives that works for monadic structures as well ..

Monads are more restrictive than applicatives. But there are quite a few use cases where you need to have a monad and NOT an applicative. One such use case is when you would like to change the sequence of an effectful computation depending on a previous outcome.

A use case for monads

Have a look at the function ifM (monadic if) defined in scalaz ..

// executes the true branch of ifM
scala> true.some ifM(none[Int], 4.some)
res8: Option[Int] = None

Here's how ifM is defined ..

def ifM[B](t: => M[B], f: => M[B])(implicit a: Monad[M], b: A <:< Boolean): M[B] = 
  >>= ((x: A) => if (x) t else f)

It uses the monadic bind that can influence a subsequent computation depending on the outcome of a previous computation.

(>>=) :: m a -> (-> m b) -> m b

Now consider the same computation implemented using an applicative ..

scala> val ifA = (b: Boolean) => (t: Int) => (f: Int) => (if (b) t else f)            
ifA: (Boolean) => (Int) => (Int) => Int = <function1>

// good!
scala> none <*> (some(12) <*> (some(false) map ifA)) 
res41: Option[Int] = None

// bad!
scala> none <*> (some(12) <*> (some(true) map ifA)) 
res42: Option[Int] = None

<*> just sequences the effects through all computation structures - hence we get the last effect as the return value which is the one for the else branch. Have a look at the last snippet where even though the condition is true, we have the else branch returned.

(<*>) :: f(-> b) -> f a -> f b

So <*> cannot change the structure of the computation which remains fixed - it just sequences the effects through the chain.

Monads are the correct way to model your effectful computation when you would like to control the structure of computation depending on the context.

A use case for applicatives

scalaz implements Validation as an applicative functor. This is because here we need to accumulate all the effects that the validation can produce. As I noted in my last post on composing abstractions in scalaz, the following snippet will accumulate all validation errors before bailing out .. quite unlike a monadic API ..

def makeTrade(account: Account, instrument: Instrument, refNo: String, market: Market, 
  unitPrice: BigDecimal, quantity: BigDecimal) =
  (validUnitPrice(unitPrice).liftFailNel |@| 
    validQuantity(quantity).liftFailNel) { (u, q) => Trade(account, instrument, refNo, market, u, q) }

Let's look into it in a bit more detail ..

sealed trait Validation[+E, +A] {

final case class Success[E, A](a: A) extends Validation[E, A]
final case class Failure[E, A](e: E) extends Validation[E, A]

Note in case of success only the actual computation value gets propagated, as in the following ..

trait Validations {
  def success[E, A](a: A): Validation[E, A] = Success(a)
  def failure[E, A](e: E): Validation[E, A] = Failure(e)

With a monadic bind, the computation will be aborted on the first error as we don't have the computation value to be passed to the second argument of >>=. Applicatives allow us to sequence through the computation chain nicely and accumulate all the effects. Hence we can get effects like ..

// failure case
scala> makeTrade("a-123", "google", "ref-12", Singapore, -10, 600)
res2: scalaz.Validation[scalaz.NonEmptyList[String],] = 
  Failure(NonEmptyList(price must be > 0, qty must be <= 500))

One other interesting abstraction to manipulate computation structures is an Arrow, which makes an interesting comparison with Applicative Functors. But that's for some other day, some other post ..

Wednesday, December 01, 2010

Composable domain models using scalaz

I have been having some solid fun working through scalaz - it's possibly as close you can get to Haskell with a postfunctional language like Scala, which also supports object oriented paradigms. One of the ways I do learn languages is by developing domain models using the idioms that the language offers and try to make the model as expressive as possible. I pick up domains on which I have worked before - so I have an idea of how much I can gain in epressivity using the new language compared to implementations in older languages.

Securities trading is a domain on which I have been working since the last 10 years. I have implemented domain models of securities trading back office systems in Java and Scala. It's time to add scalaz to the mix and see how much more functional my model turns out to be. I have created a playground for this - tryscalaz is a repository on my github that hosts some of my experiments with scalaz. I have started building a domain model for trading systems. It's far from being a realistic one for production use - its main purpose is to make myself more conversant with scalaz.

Scalaz is a wonderful experiment - it's definitely what functional Scala programs should look like. It has a small but wonderful community - Jason (@retronym) and Runar (@runarorama) always help me proactively both on the mailing list and on Twitter.

I am not going into every detail of how my trade domain model shapes up with Scalaz. I implemented a similar domain model in Haskell very recently and documented it here, here and here on my blog. If nothing else, it will help you compare the various aspects of both the implementations.

In this post let me go through some of the features of Scalaz that I found wonderfully expressive to model your domain constraints. You can get a lot out of using Scala only. But with Scalaz, you can take your composition at a much higher level through the various combinators that it offers as part of implementing typeclasses for functors, applicatives, monads and arrows. I haven't yet explored all of these abstractions - yet many of those are already very useful in making your domain models concise, yet expressive.

Here's some example of composition using the higher order functions that Scalaz offers ..

Note how we can compose the functions much like the Haskell way that I described in the earlier posts. In the above composition, I used map, which we can do in Scala for lists or options which explicitly support a map operation that maps a function over the collection. With scalaz we can use mapping of a function over any A of kind *->* for which there exists a Functor[A]. Scala supports higher kinds and scalaz uses it to make map available more generally than what you get in the Scala standard library.

Now let's infuse some more Scalaz magic into it. Frequently we need to do the same operations on a list of trades, which means that instead of just a map, we need to lift the functions through another level of indirection. Much like ..

Note how the functions forTrade, taxFees etc. get lifted into the List of Options.

Another nice feature that becomes extremely useful with scalaz in a domain model is the use of non-breaking error handling. This is made elegant by designing the Validation[] abstraction as an applicative functor. You can design your validation functions of the domain model as returning an instance of Validation[]. They can then be wired together in a variety of ways to implement accumulation of all failures before reporting to the user .. Here's a simple example from the Trade domain model ..

Validation[] in scalaz works much like Either[], but has a more expressive interface that specifies the success and error types explicitly ..

You can use Validation[] in comprehensions or as an applicative functor and wire up your domain validation logic in a completely functional way. Here's how our above validations work on the REPL ..

When we have invalid trade arguments all validation errors are accumulated and then reported to the user. If all arguments are valid, then we have a valid Trade instance as success. Cool stuff .. a recipe that I would like to have as part of my domain modeling everytime I start a new project ..

Monday, November 22, 2010

Exploring scalaz

I have been playing around with Scalaz for a couple of weekends now. Scalaz brings to Scala some generic functions and abstractions that are not there in the current Scala API. These are mostly *functional* higher order structures that Haskell boasts as being part of their standard distribution. Using Scalaz you can write Scala code in applicative style that often come out as being more expressive than the imperative one.

Functors, applicatives, arrows, monads and many such abstractions form part of the Scalaz repertoire. It’s no wonder that using Scalaz needs a new way of thinking on your part than is with standard Scala. You need to think more like as if you’re modeling in Haskell rather than in any object-oriented language.

Typeclasses are the cornerstone of Scalaz distribution. Instead of thinking polymorphically in inheritance hierarchies, think in terms of designing APIs for the open world using typeclasses. Scalaz implements the Haskell hierarchy of typeclasses - Functors, Pointed, Applicative, Monad and the associated operations that come with them.

How is this different from the normal way of thinking ? Let’s consider an example from the current Scala point of view.

We say that with Scala we can design monadic abstractions. flatMap is the bind which helps us glue abstractions just like you would do with >>= of Haskell. But does the Scala standard library really have a monad abstraction ? No! If it had a monad then we would have been able to abstract over it as a separate type and implement APIs like sequence in Haskell ..

sequence :: Monad m => [m a] -> m [a]

We don’t have this in the Scala standard library. Consider another example of a typeclass, Applicative, which is defined in Haskell as

class Functor f => Applicative f where
  pure :: a -> f a
  (<*>) :: f (-> b) -> f a -> f b

Here pure lifts a into the effectful environment of the functor, while (<*>) takes a function from within the functor and applies it over the values of the functor. Scalaz implements Applicative in Scala, so that you can write the following:

scala> import scalaz._
import scalaz._

scala> import Scalaz._
import Scalaz._

scala> List(10, 20, 30) <*> (List(1, 2, 3) map ((_: Int) * (_: Int)).curried)
res14: List[Int] = List(10, 20, 30, 20, 40, 60, 30, 60, 90)

Here we have a pure function that multiplies 2 Ints. We curry the function and partially apply to the members of the List(1, 2, 3). Note List is an instance of Applicative Functor. Then we get a List of partial applications. Finally <*> takes that List and applies to every member of List(10, 20, 30) as a cartesian product. Of course the Haskell variant is much less verbose ..

(*) <$> [1, 2, 3] <*> [10, 20, 30]

and this is due to better type inference and curry by default strategy of function application.

You can get a more succinct variant in Scalaz using the |@| combinator ..

scala> List(10, 20, 30) |@| List(1, 2, 3) apply (* _)
res17: List[Int] = List(10, 20, 30, 20, 40, 60, 30, 60, 90)

You can have many instances of Applicatives so long you implement the contract that the above definition mandates. Typeclasses give you the option to define abstractions for the open world. Like List, there are many other applicatives implemented in Scalaz like options, tuples, function applications etc. The beauty of this implementation is that you can abstract over them in a uniform way through the power of the Scala type system. Just like List, you can apply <*> over options as well ..

scala> some(10) <*> (some(20) map ((_: Int) * (_: Int)).curried)
res18: Option[Int] = Some(200)

And since all Applicatives can be abstracted over without looking at the exact concrete type, here’s one that mixes an option with a function application through <*> ..

scala> some(9) <*> some((_: Int) + 3)
res19: Option[Int] = Some(12)

The Haskell equivalent of this one is ..

Just (+3) <*> Just 9

Scalaz uses two features of Scala to the fullest extent - higher kinds and implicits. The entire design of Scalaz is quite unlike the usual Scala based design that you would encounter elsewhere. Sometimes you will find these implementations quite opaque and verbose. But most of the verbosity comes from the way we encode typeclasses in Scala using implicits. Consider the following definition of map, which is available as a pimp defined in the trait MA ..

sealed trait MA[M[_], A] extends PimpedType[M[A]] {
  import Scalaz._
  def map[B](f: A => B)(implicit t: Functor[M]): M[B] = //..

map takes a pure function (f: A => B) and can be applied on any type constructor M so long it gets an instance of a Functor[M] in its implicit context. Using the trait we pimp the specific type constructor with the map function.

Here are some examples of using applicatives and functors in Scalaz. For fun I had translated a few examples from Learn You a Haskell for Great Good. I also mention the corresponding Haskell version for each of them ..

// pure (+3) <*> Just 10 << from lyah
10.pure[Option] <*> some((_: Int) + 3) should equal(Some(13))

// pure (+) <*> Just 3 <*> Just 5 << lyah
// Note how pure lifts the function into Option applicative
// scala> p2c.pure[Option]
// res6: Option[(Int) => (Int) => Int] = Some(<function1>)

// scala> p2c
// res7: (Int) => (Int) => Int = <function1>
val p2c = ((_: Int) * (_: Int)).curried
some(5) <*> (some(3) <*> p2c.pure[Option]) should equal(Some(15))

// none if any one is none
some(9) <*> none should equal(none)

// (++) <$> Just "johntra" <*> Just "volta" << lyah
some("volta") <*> (some("johntra") map (((_: String) ++ (_: String)).curried)) 
  should equal(Some("johntravolta"))

// more succinct
some("johntra") |@| (some("volta") apply (++ _) should equal(Some("johntravolta"))

Scalaz is mind bending. It makes you think differently. In this post I have only scratched the surface and talked about a couple of typeclasses. But the only way to learn Scalaz is to run through the codebase. It's dense but if you like functional programming you will get lots of aha! moments going through it.

In the next post I will discuss how I translated part of a domain model of a financial trade system which I wrote in Haskell (Part 1, Part 2 and Part 3) into Scalaz. It has been a fun exercise for me and shows how you can write your Scala code in an applicative style.

Monday, November 01, 2010

Domain Modeling in Haskell - Applicative Functors for Expressive Business Rules

In my last post on domain modeling in Haskell, we had seen how to create a factory for creation of trades that creates Trade from an association list. We used monadic lifts (liftM) and monadic apply (ap) to chain our builder that builds up the Trade data. Here's what we did ..

makeTrade :: [(String, Maybe String)] -> Maybe Trade
makeTrade alist =
    Trade `liftM` lookup1 "account"                      alist
             `ap` lookup1 "instrument"                   alist
             `ap` (read `liftM` (lookup1 "market"        alist))
             `ap` lookup1 "ref_no"                       alist
             `ap` (read `liftM` (lookup1 "unit_price"    alist))
             `ap` (read `liftM` (lookup1 "quantity"      alist))

lookup1 key alist = case lookup key alist of
                      Just (Just s@(_:_)) -> Just s
                      _ -> Nothing

Immediately after the post, I got some useful feedback on Twitter suggesting the use of applicatives instead of monads. A Haskell newbie, that I am, this needed some serious explorations into the wonderful world of functors and applicatives. In this post let's explore some of the goodness that applicatives offer, how using applicative style of programming encourages a more functional feel and why you should always use applicatives unless you need the special power that monads offer.

Functors and Applicatives

In Haskell a functor is a typeclass defined as

class Functor f where
  fmap :: (-> b) -> f a -> f b

fmap lifts a pure function into a computational context. For more details on functors, applicatives and all of typeclasses, refer to the Typeclassopedia that Brent Yorgey has written. In the following text, I will be using examples from our domain model of securities trading. After all, I am trying to explore how Haskell can be used to build expressive domain models with a very popular domain at hand.

Consider the association list rates from our domain model in my last post, which stores pairs of tax/fee and the applicable rates as percentage on the principal.

*Main> rates

We would like to increase all rates by 10%. fmap is our friend here ..

*Main> fmap (\(tax, amount) -> (tax, amount * 1.1)) rates

This works since List is an instance of the Functor typeclass. The anonymous function gets lifted into the computational context of the List data type. But the code looks too verbose, since we have to destructure the tuple within the anonymous function and thread the increment logic manually within it. We can increase the level of abstraction by making the tuple itself a functor. In fact it's so in Haskell and the function gets applied to the second component of the tuple. Here's the more idiomatic version ..

*Main> ((1.1*) <$>) <$> rates

Note how we lift the function across 2 levels of functors - a list and within that, a tuple. fmap does the magic! The domain model becomes expressive through the power of Haskell's higher level of abstractions.

Applicatives add more power to functors. While functors lift pure functions, with applicatives you can lift functions from one context into another. Here's how you define the Applicative typeclass.

class Functor f => Applicative f where
  pure :: a -> f a
  (<*>) :: f (-> b) -> f a -> f b

Note pure is the equivalent of a return in monads, while <*> equals ap.

Control.Applicative also defines a helper function <$>, which is basically an infix version of fmap. The idea is to help write functions in applicative style.

(<$>) :: Applicative f => (-> b) -> f a -> f b

Follow the types and see that f <$> u is the same as pure f <*> u.

Note also the following equivalence of fmap and <$> ..

*Main> fmap (+3) [1,2,3,4]

*Main> (+3) <$> [1,2,3,4]

Using the applicative style our makeTrade function becomes the following ..

makeTrade :: [(String, Maybe String)] -> Maybe Trade
makeTrade alist =
    Trade <$> lookup1 "account"                   alist
             <*> lookup1 "instrument"             alist
             <*> (read <$> (lookup1 "market"      alist))
             <*> lookup1 "ref_no"                 alist
             <*> (read <$> (lookup1 "unit_price"  alist))
             <*> (read <$> (lookup1 "quantity"    alist))

Can you figure out how the above invocation works ? As I said before, follow the types ..

Trade is a pure function and <$> lifts Trade onto the first invocation of lookup1, which is a Maybe functor. The result is another Maybe, which BTW is an Applicative functor as well. Then the rest of the chain continues through partial application and an applicative lifting from one context to another.

Why choose Applicatives over Monads ?

One reason is that there are more applicatives than monads. Monads are more powerful - using (>>=) :: (Monad m) => m a -> (a -> m b) -> m b you can influence the structure of your overall computation, while with applicatives your structure remains fixed. You only get sequencing of effects with an applicative functor. As an exercise try exploring the differences in the behavior of makeTrade function implemented using monadic lifts and applicatives when lookup1 has some side-effecting operations. Conor McBride and Ross Paterson has a great explanation in their functional pearl paper Applicative Programming with Effects. Applicatives being more in number, you have more options of abstracting your domain model.

In our example domain model, suppose we have the list of tax/fees and the list of rates for each of them. And we would like to build our rates data structure. ZipList applicative comes in handy here .. ZipList is an applicative defined as follows ..

instance Applicative ZipList where  
  pure x = ZipList (repeat x)  
  ZipList fs <*> ZipList xs = ZipList (zipWith (\f x -> f x) fs xs)  

*Main> getZipList $ (,) <$> ZipList [TradeTax, Commission, VAT] <*> ZipList [0.2, 0.15, 0.1]

ZipList is an applicative and NOT a monad.

Another important reason to choose applicatives over monads (but only when possible) is that applicatives compose, monads don't (except for certain pairs). The McBride and Paterson paper has lots of discussions on this.

Finally programs written with applicatives often have a more functional feel than some of the monads with the do notation (that has an intrinsically imperative feel). Have a look at the following snippet which does the classical do-style first and then follows it up with the applicative style using applicative functors.

-- classical imperative IO
notice = do
  trade <- getTradeStr
  forClient <- getClientStr
  putStrLn $ "Trade " ++ trade ++ forClient

-- using applicative style
notice = do
  details <- (++) <$> getTradeStr <*> getClientStr
  putStrLn $ "Trade " ++ details

McBride and Paterson has the final say on how to choose monads or applicatives in your design .. "The moral is this: if you’ve got an Applicative functor, that’s good; if you’ve also got a Monad, that’s even better! And the dual of the moral is this: if you want a Monad, that’s good; if you only want an Applicative functor, that’s even better!"

Applicative Functors for Expressive Business Rules

As an example from our domain model, we can write the following applicative snippet for calculating the net amount of a trade created using makeTrade ..

*Main> let trd = makeTrade [("account", Just "a-123"), ("instrument", Just "IBM"), 
                   ("market", Just "Singapore"), ("ref_no", Just "r-123"), 
                   ("unit_price", Just "12.50"), ("quantity", Just "200" )]
*Main> netAmount <$> enrichWith . taxFees . forTrade <$> trd
Just 3625.0

Note how the chain of functions get lifted into trd (Maybe Trade) that's created by makeTrade. This is possible since Maybe is an applicative functor. The beauty of applicative functors is that you can abstract this lifting into any of them. Let's lift the chain of invocation into a list of trades generating a list of net amount values for each of them. Remember List is also another applicative functor in Haskell. For a great introduction to applicatives and functors, go read Learn Yourself a Haskell for Great Good.

*Main> (netAmount <$> enrichWith . taxFees . forTrade <$>) <$> [trd2, trd3]
[Just 3625.0,Just 3375.0]

Look how we have the minimum of syntax with this applicative style. This makes business rules very expressive and not entangled into a maze of accidental complexity.