Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to find programming exercises for applicative functors?

I've been reading about applicative functors, notably in the Functional Pearl by McBride and Paterson. But I'd like to solidify my understanding by doing some exercises. I'd prefer programming exercises but proof exercises are OK too. What exercises will help me learn to program effectively with applicative functors?

Individual exercises are OK as are pointers to exercises listed elsewhere.

like image 460
Norman Ramsey Avatar asked Apr 20 '12 02:04

Norman Ramsey


People also ask

What is applicative in functional programming?

In functional programming, an applicative functor, or an applicative for short, is an intermediate structure between functors and monads.

What is applicative in Scala?

Applicative is a generalization of Monad , allowing expression of effectful computations in a pure functional way. Applicative is generally preferred to Monad when the structure of a computation is fixed a priori. That makes it possible to perform certain kinds of static analysis on applicative values.

Are all monads functors?

As I understand, every monad is a functor but not every functor is a monad. A functor takes a pure function (and a functorial value) whereas a monad takes a Kleisli arrow, i.e. a function that returns a monad (and a monadic value).

What are Functors Applicatives and monads?

A functor is a data type that implements the Functor typeclass. An applicative is a data type that implements the Applicative typeclass. A monad is a data type that implements the Monad typeclass. A Maybe implements all three, so it is a functor, an applicative, and a monad.


2 Answers

It seems amusing to post some questions as an answer. This is a fun one, on the interplay between Applicative and Traversable, based on sudoku.

(1) Consider

data Triple a = Tr a a a 

Construct

instance Applicative Triple instance Traversable Triple 

so that the Applicative instance does "vectorization" and the Traversable instance works left-to-right. Don't forget to construct a suitable Functor instance: check that you can extract this from either of the Applicative or the Traversable instance. You may find

newtype I x = I {unI :: x} 

useful for the latter.

(2) Consider

newtype (:.) f g x = Comp {comp :: f (g x)} 

Show that

instance (Applicative f, Applicative g) => Applicative (f :. g) instance (Traversable f, Traversable g) => Traversable (f :. g) 

Now define

type Zone = Triple :. Triple 

Suppose we represent a Board as a vertical zone of horizontal zones

type Board = Zone :. Zone 

Show how to rearrange it as a horizontal zone of vertical zones, and as a square of squares, using the functionality of traverse.

(3) Consider

newtype Parse x = Parser {parse :: String -> [(x, String)]} deriving Monoid 

or some other suitable construction (noting that the library Monoid behaviour for |Maybe| is inappropriate). Construct

instance Applicative Parse instance Alternative Parse  -- just follow the `Monoid` 

and implement

ch :: (Char -> Bool) -> Parse Char 

which consumes and delivers a character if it is accepted by a given predicate.

(4) Implement a parser which consumes any amount of whitespace, followed by a single digit (0 represents blanks)

square :: Parse Int 

Use pure and traverse to construct

board :: Parse (Board Int) 

(5) Consider the constant functors

newtype K a x = K {unK :: a} 

and construct

instance Monoid a => Applicative (K a) 

then use traverse to implement

crush :: (Traversable f, Monoid b) => (a -> b) -> f a -> b 

Construct newtype wrappers for Bool expressing its conjunctive and disjunctive monoid structures. Use crush to implement versions of any and all which work for any Traversable functor.

(6) Implement

duplicates :: (Traversable f, Eq a) => f a -> [a] 

computing the list of values which occur more than once. (Not completely trivial.) (There's a lovely way to do this using differential calculus, but that's another story.)

(7) Implement

complete :: Board Int -> Bool ok :: Board Int -> Bool 

which check if a board is (1) full only of digits in [1..9] and (2) devoid of duplicates in any row, column or box.

like image 85
pigworker Avatar answered Sep 18 '22 05:09

pigworker


A great way to practice is to use Parsec in an applicative rather than a monadic style. Most parsers are purely applicative, so you shouldn't need to use do notation ever.

Eg. for expressions:

import qualified Text.Parsec as P import qualified Text.Parsec.Token as P import Control.Applicative  data Expr = Number Int | Plus Expr Expr  lex = P.makeTokenParser ...  -- language config  expr = number <|> plus     where     number = Number <$> P.integer lex     plus = Plus <$> number <* P.symbol lex "+" <*> expr 
like image 43
luqui Avatar answered Sep 18 '22 05:09

luqui