Why should I use applicative functors in functional programming?

I am new to Haskell and I read about functors and applicative functors. Ok, I understand functors and how I can use them, but I don't understand why applicative functors are useful and how I can use them in Haskell. Can you explain to me a simple example why I need applicative functors?

+63
functor functional-programming haskell
Jul 04 '11 at 11:21
source share
7 answers

Applicative functors are a construction that provides a midpoint between functors and monads , and therefore are more common than monads, but more useful than functors. Usually you can just map a function over a functor. Applicative functions allow you to perform a "normal" function (by accepting non-functorial arguments), using it to work with multiple values โ€‹โ€‹that are in the contexts of a functor. As a result, this gives you effective programming without monads.

A good, self-sufficient explanation fraught with examples can be found here . You can also read a practical example of parsing developed by Brian O'Sullivan, which does not require prior knowledge.

+45
Jul 04 2018-11-11T00:
source share

Applicative functors are useful when you need a sequence of actions, but do not need to specify intermediate results. They are, therefore, weaker than monads, but stronger than functors (they do not have an explicit binding operator, but they allow you to run arbitrary functions inside a functor).

When are they helpful? A common example is parsing, when you need to perform a series of actions that read parts of a data structure and then glue all the results together. This is similar to the general form of functional composition:

fabcd 

where you can think of a , b , etc. as arbitrary actions to run, and f as a functor applied to the result.

 f <$> a <*> b <*> c <*> d 

I like to think of them as an overloaded โ€œgapโ€. Or that the regular Haskell functions are in the identical applicative functor.

See Applicative Programming with Effects .

+29
Jul 07 2018-11-18T00:
source share

Conor McBride and Ross Paterson The functional pearl in style has some good examples. It is also responsible for popularizing the style in the first place. They use the term "idiom" for "applied functor", but other than that it is pretty clear.

+12
Jul 04 '11 at 13:15
source share

It is difficult to find examples in which you need applicative functors. I can understand why the intermediate Haskell programmer asked them this question, since most introductory texts present instances obtained from Monads using applicative functors only as a convenient interface.

The key insight, as mentioned here and in most of the ideas on this subject, is that Applicative Functors are between Functors and Monads (even between Functors and Arrows). All Monads are applicative functors, but not all Functors are applicative.

Therefore, it is imperative, sometimes we can use applicative combinators for something for which we cannot use monadic combinators. One such thing is a ZipList (see also this SO question for some details ), which is just a wrapper around lists to have a different applicative instance than the one obtained from the Monad instance of the list. In the Application Documentation, the following line is used to give an intuitive idea of โ€‹โ€‹what ZipList for:

 f <$> ZipList xs1 <*> ... <*> ZipList xsn = ZipList (zipWithn f xs1 ... xsn) 

As stated here , you can make fancy Monad instances that almost work for ZipList.

There are other applicative functors that are not Monads (see this SO question) and are easy to come up with. Having an alternative interface for Monads is nice and all, but sometimes creating a Monad is inefficient, difficult, or even impossible, and that's when you need applicative functors.




Disclaimer: creating applicative functors can also be inefficient, complex, and impossible; if in doubt, contact your local category theorist for the correct use of applicative functors.

+8
Oct 17 '11 at 18:08
source share

One good example: applicative parsing.

See [real haskell] ch16 http://book.realworldhaskell.org/read/using-parsec.html#id652517

This is the parser code with do-notation:

 -- file: ch16/FormApp.hs p_hex :: CharParser () Char p_hex = do char '%' a <- hexDigit b <- hexDigit let ((d, _):_) = readHex [a,b] return . toEnum $ d 

Using a functor, make it much shorter :

 -- file: ch16/FormApp.hs a_hex = hexify <$> (char '%' *> hexDigit) <*> hexDigit where hexify ab = toEnum . fst . head . readHex $ [a,b] 

Rising can obscure the basic details of some repeating code. then you can simply use fewer words to tell an accurate and accurate story.

+6
Jul 04 '11 at 16:18
source share

In my experience, applicative functors are great for the following reasons:

Some types of data structures allow powerful composition types, but monads cannot actually be made. In fact, most abstractions in functional reactive programming fall into this category. Although we may technically be able to make, for example, a Behavior (aka Signal ) monad, it usually cannot be performed efficiently. Applicative functions allow us to still have powerful compositions without sacrificing efficiency (admittedly, itโ€™s a little more difficult to use applicative than a monad, sometimes because you donโ€™t have much structure to work with).

The absence of data dependence in the applicative functor allows you, for example, go to the action, looking for all the effects that it can produce without data. Thus, you can imagine the application of the "web form" used as follows:

 userData = User <$> field "Name" <*> field "Address" 

and you can write an engine that will move to find all the fields used and display them in the form, and then when you run the data again, run the built User . This cannot be done with a simple functor (because it combines two forms into one) and monads, because with a monad you can express:

 userData = do name <- field "Name" address <- field $ name ++ " address" return (User name address) 

which cannot be displayed, because the name of the second field cannot be known without already responding from the first. I am pretty sure that there is a library that implements the idea of โ€‹โ€‹this form. I rolled back this and this project several times.

Another nice thing about applicative functors is that they compose. More precisely, a composition functor:

 newtype Compose fgx = Compose (f (gx)) 

applies when f and g . The same cannot be said for monads, which created the entire history of the transformation of the monad, which is complicated by some unpleasant ways. Applicable methods are super-clean in this way, and this means that you can create the structure of the required type by focusing on the small constituents.

Recently, the ApplicativeDo extension has appeared in the GHC, which allows you to use do notation with applications, easing some of the notation complexity if you don't do any monotonous things.

+6
Dec 27 '16 at 2:20
source share

I would also suggest taking a look at this

An example is given at the end of the article.

 import Control.Applicative hasCommentA blogComments = BlogComment <$> lookup "title" blogComments <*> lookup "user" blogComments <*> lookup "comment" blogComments 

Which illustrates several features of the applied programming style.

+3
Feb 29 '12 at 6:50
source share



All Articles