Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the applicative functor laws in terms of pure and liftA2?

I'm playing around with formulating Applicative in terms of pure and liftA2 (so that (<*>) = liftA2 id becomes a derived combinator).

I can think of a bunch of candidate laws, but I'm not sure what the minimal set would be.

  1. f <$> pure x = pure (f x)
  2. f <$> liftA2 g x y = liftA2 ((f .) . g) x y
  3. liftA2 f (pure x) y = f x <$> y
  4. liftA2 f x (pure y) = liftA2 (flip f) (pure y) x
  5. liftA2 f (g <$> x) (h <$> y) = liftA2 (\x y -> f (g x) (h y)) x y
  6. ...
like image 707
Alan O'Donnell Avatar asked Mar 12 '15 18:03

Alan O'Donnell


People also ask

What are functor laws?

Functor Laws If two sequential mapping operations are performed one after the other using two functions, the result should be the same as a single mapping operation with one function that is equivalent to applying the first function to the result of the second.

Is applicative a functor?

Applicative functors are the programming equivalent of lax monoidal functors with tensorial strength in category theory. Applicative functors were introduced in 2008 by Conor McBride and Ross Paterson in their paper Applicative programming with effects.

Could you comfortably explain the difference between a monad and an applicative functor?

Functors apply a function to a wrapped value: Applicatives apply a wrapped function to a wrapped value: Monads apply a function that returns a wrapped value to a wrapped value. Monads have a function >>= (pronounced "bind") to do this.

How many methods should a functor instance have?

Functor in Haskell is a typeclass that provides two methods – fmap and (<$) – for structure-preserving transformations. To implement a Functor instance for a data type, you need to provide a type-specific implementation of fmap – the function we already covered.


1 Answers

Based on McBride and Paterson's laws for Monoidal(section 7) I'd suggest the following laws for liftA2 and pure.

left and right identity

liftA2 (\_ y -> y) (pure x) fy       = fy
liftA2 (\x _ -> x) fx       (pure y) = fx

associativity

liftA2 id           (liftA2 (\x y z -> f x y z) fx fy) fz =
liftA2 (flip id) fx (liftA2 (\y z x -> f x y z)    fy  fz)

naturality

liftA2 (\x y -> o (f x) (g y)) fx fy = liftA2 o (fmap f fx) (fmap g fy)

It isn't immediately apparent that these are sufficient to cover the relationship between fmap and Applicative's pure and liftA2. Let's see if we can prove from the above laws that

fmap f fx = liftA2 id (pure f) fx

We'll start by working on fmap f fx. All of the following are equivalent.

fmap f fx
liftA2 (\x _ -> x) (fmap f fx) (         pure y )     -- by right identity
liftA2 (\x _ -> x) (fmap f fx) (     id (pure y))     -- id x = x by definition
liftA2 (\x _ -> x) (fmap f fx) (fmap id (pure y))     -- fmap id = id (Functor law)
liftA2 (\x y -> (\x _ -> x) (f x) (id y)) fx (pure y) -- by naturality
liftA2 (\x _ -> f x                     ) fx (pure y) -- apply constant function

At this point we've written fmap in terms of liftA2, pure and any y; fmap is entirely determined by the above laws. The remainder of the as-yet-unproven proof is left by the irresolute author as an exercise for the determined reader.

like image 155
Cirdec Avatar answered Oct 15 '22 01:10

Cirdec