Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ApplicativeDo in Haskell

AFAIK one of the new additions to GHC8 is the ApplicativeDo language extension, which desugars the do-notation to the corresponding Applicative methods (<$>, <*>) if possible. I have the following questions.

How does it decide whether the desugaring to Applicative methods is possible? From what I know, it does a dependency check (if the later depends on the result of former) to decide the eligibility. Are there any other criteria?

Although this addition makes applicative code easier to read for classes that don't have any Monad instance (maybe ?). But for structures that both have a Monad and an Applicative instance: Is this a recommended practice (from the readability perspective)? Are there any other benefits?

like image 486
zeronone Avatar asked Nov 19 '16 05:11

zeronone


People also ask

What is applicative in Haskell?

Definition. In Haskell, an applicative is a parametrized type that we think of as being a container for data of that type plus two methods pure and <*> . Consider a parametrized type f a . The pure method for an applicative of type f has type. pure :: a -> f a.

What are Functors in Haskell?

Functor in Haskell is a kind of functional representation of different Types which can be mapped over. It is a high level concept of implementing polymorphism. According to Haskell developers, all the Types such as List, Map, Tree, etc. are the instance of the Haskell Functor.

Is <*> the same as *> Haskell?

They are equivalent, in practice.

What is a Haskell monad?

What is a Monad? A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.


1 Answers

How does it decide whether the desugaring to Applicative methods is possible? From what I know, it does a dependency check (if the later depends on the result of former) to decide the eligibility. Are there any other criteria?

The paper and trac page are the best sources of information. Some points:

  • ApplicativeDo uses applicatives wherever possible - including mixing them with >>= in some cases where only part of the do block is applicative
  • A sort of directed graph of dependencies is constructed to see which parts can be "parallelized"
  • Sometimes there is no obvious best translation of this graph! In this case, GHC chooses the translation that is (roughly speaking) locally smallest

Although this addition makes applicative code easier to read for classes that don't have any Monad instance (maybe ?). But for structures that both have a Monad and an Applicative instance: Is this a recommended practice (from the readability perspective)? Are there any other benefits?

Here is an answer about the difference between Applicative and Monad. To quote directly:

To deploy <*>, you choose two computations, one of a function, the other of an argument, then their values are combined by application. To deploy >>=, you choose one computation, and you explain how you will make use of its resulting values to choose the next computation. It is the difference between "batch mode" and "interactive" operation.

A prime example of this sort of thing is the Haxl monad (designed by Facebook) which is all about fetching data from some external source. Using Applicative, these requests can happen in parallel while Monad forces the requests to be sequential. In fact, this example is what motivated Simon Marlow at Facebook to make the ApplicativeDo extension in the first place and write the quoted paper about it.

In general, most Monad instances don't necessarily benefit from Applicative. From the same answer I quoted above:

I appreciate that ApplicativeDo is a great way to make more applicative (and in some cases that means faster) programs that were written in monadic style that you haven't the time to refactor. But otherwise, I'd argue applicative-when-you-can-but-monadic-when-you-must is also the better way to see what's going on.

So: use Applicative over Monad when possible, and exploit ApplicativeDo when it really is nicer to write (like it must have been in some cases at Facebook) than the corresponding applicative expression.

like image 132
Alec Avatar answered Nov 01 '22 18:11

Alec