[Haskell-cafe] On to applicative
michael rice
nowgate at yahoo.com
Thu Aug 26 12:27:44 EDT 2010
Hi Alexander,
Didn't get to sleep till 4 AM and it took me a while to go though your post.
So far...
--- On Thu, 8/26/10, Alexander Solla <ajs at 2piix.com> wrote:
From: Alexander Solla <ajs at 2piix.com>
Subject: Re: [Haskell-cafe] On to applicative
To:
Cc: "haskell-cafe Cafe" <haskell-cafe at haskell.org>
Date: Thursday, August 26, 2010, 4:29 AM
On Aug 26, 2010, at 12:34 AM, michael rice wrote:
> A lot of stuff to get one's head around. Was aware of liftM2, liftM3, etc., but not liftA2, liftA3, etc.
>
liftM and liftA are essentially equivalent (and are both essentially equivalent to fmap) Same for the liftAn = liftMn functions (where n is an integer). Applicative functors are more general than monads, so it makes sense for them to have their own functions. It is a matter of history that liftM was defined before liftA.
> So, the statement was true, but not the way that was shown in the example, i.e., with fmap2, fmap3, etc., which required different functions for each of the fmaps.
Strictly speaking, fmap will work with a function in more than one argument, as long as it is properly typed. This is what makes applicative functors work.
Consider that a function f :: a -> b -> c also has the type f :: a -> (b -> c). If you feed it an "a", (resulting in a value of the form f a), you get a function g :: (b -> c). In other words, every function is a function in one argument.
### Knew that fact, but it needed to be dusted off.
Some functions just happen to map to other functions.
<$> is flip fmap. f <$> functor = fmap f functor #### Brent Yorgey's post noted.
#### "map to"? Take as arguments?
Consider what happens if f :: a -> b. (f <$> functor) means "pull an a out of the functor, apply f, and return a functor "over" some b. That is to say, "lift" f into the functor and apply it.
#### OK.
#### Prelude Control.Applicative> let double x = x+x
#### Prelude Control.Applicative> (double <$> (Just 7))
#### Just 14
Now consider what happens if f :: a -> (b -> c). By analogy, this means "pull an a out of the functor object, apply f, and return a functor object (f g) :: f (b -> c)" (In other words, a functor object that "contains" a function g :: b -> c). In order to get a c value out of this, you need to apply g to "something". But note that we're not just dealing with g. It is "in" the functor already, and so doesn't need lifting. So some smart guy wrote a function called
<*> :: (Functor f) => f (b -> c) -> f b -> f c
#### Prelude Control.Applicative> let plus x y = x+y
#### Prelude Control.Applicative> let f = (plus <$> (Just 3))
#### Prelude Control.Applicative> f (Just 4)
#### <interactive>:1:0:
#### Couldn't match expected type `Maybe t1 -> t'
#### against inferred type `Maybe (Integer -> Integer)'
#### In the expression: f (Just 4)
#### In the definition of `it': it = f (Just 4)
#### Prelude Control.Applicative> f <*> (Just 4)
#### Just 7
#### OK. Partial evaluation with functors?
that does just that. This is one of the defining functions for an applicative functor. (And part of the reason for the name. If the functor contains a function, you can "apply the functor" to properly typed functor objects.)
The other function is pure :: (a -> b) -> f (a -> b). It takes a function and lifts it into the functor, without applying it to anything. In other words, given an f :: a -> b,
pure f <*> functor = f <$> functor
#### Prelude Control.Applicative> pure double <*> (Just 5)
#### Just 10
#### Not so, the f got applied or where did we get the 10? Not sure, is this the #### "mistake" you point out in your second post?
#### Two ways of doing the same thing?
#### 1)
#### Prelude Control.Applicative> (double <$> (Just 7))
#### Just 14
#### 2)
#### Prelude Control.Applicative> pure double <*> (Just 7)
#### Just 14
#### Still looking at rest of your post.
If f has a bigger type (say, a -> b -> c -> d), you can do things like:
f <$> functor_on_a <*> functor_on_b <*> functor_on_c
Every monad is an applicative functor. If we have a monad action m_f :: m (a -> b), and another one m_a :: (m a), we can get a monad action in type (m b) by pulling the function f :: a -> b out of the first one and applying it to the b in the second one:
m_f >>= (\f -> liftM f m_a)
or... m_f >>= (flip liftM) m_a
In fact, there is a function called ap :: m (a -> b) -> m a -> m b which does just that, and is "essentially equivalent" to <*>. Of course, running return on a function f is equivalent to running pure on f.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe at haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20100826/e78aa68b/attachment.html
More information about the Haskell-Cafe
mailing list