What do the symbols <$>
and <*>
mean?
Also, I find some information about <$
and $>
.
These operators are defined in Control.Applicative
. The <$>
operator is just an infix version of fmap
:
f <$> a = fmap f a
And <*>
is part of the Applicative
typeclass definition:
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
You can search for Haskell functions and operators more easily with hoogle.
The Applicative
typeclass come in between Functor
and Monad
:
class Functor where ...
class Functor f => Applicative f where ...
class Applicative m => Monad m where ...
(Note that this is relationship between Applicative
and Monad
only enforced in the recently released GHC 7.10)
Applicatives are structures that follow specific rules. It's more powerful than a functor but less powerful than a monad. Specifically a functor can only apply a single-argument function to values in a structure, returning a new structure that contains new values but not a new shape. The canonical example is fmap (+1) [1,2,3] == [2,3,4]
, the length of the input list is always the same as the output list. With applicatives, you can apply a multi-argument pure function across multiple structures:
> (+) <$> [1, 2, 3] <*> [10, 20]
[11, 21, 12, 22, 13, 23]
The output list's length (its "shape") depends on the lengths of the input lists. However, something to note is that the length of the output list does not depend on the values inside the list. This is the power that monads add to this hierarchy:
> print $ do a <- [1, 2, 3]; b <- replicate a 10; return (a + b)
[11, 12, 12, 13, 13, 13]
Here we are combining two structures together, one of which has a "shape" that depends on the values in the other. This is not possible with just applicatives, and it's the reason why monads are so ubiquitous in Haskell. However, since every Monad
is an Applicative
and every Applicative
a Functor
, you still have access to all these tool when working with Monad
s.
<$>
is a synonymous of fmap, <$>
is the infix operator. It usually used in the context of an applicative functor.
import Control.Applicative ((<$>)
-- (<$>), fmap :: Functor f => (a -> b) -> f a -> f b
example1 :: (Int -> Int) -> Maybe Int -> Maybe Int
example1 f g = f <$> g -- f `fmap` (Just x) = Just (f x)
-- f `fmap` Nothing = Nothing
On the other hand the <*>
is useful when you have a function in the context of a functor and you want to apply that to some value in a another functor context, for instance:
example2:: Maybe (Int -> Int) -> Maybe Int -> Maybe Int
example2 f g = f <*> g -- (Just f) <*> (Just x) = Just ( f x)
-- Nothing <*> (Just x ) = Nothing
-- (Just f) <*> Nothing = Nothing
-- Nothing <*> Nothing = Nothing
It can be pictured as an operator that applies a function and simultaneously takes into account the context in which the function is applied.
These operators lift the values and functions to the context of the Functor in which the operations are carry out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With