What are these operators doing?
(.) :: (b -> c) -> (a -> b) -> a -> c
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
I don't have any idea when I see the signatures. Perhaps some example with a simple and easy to understand explanation will help me.
I am also learning Haskell, and my recommendation is to have a look into Learn You a Haskell for Great Good!, and more precisely:
for (.) read Function composition
for <$> and <*> read Applicative functors
In essence:
(.) is function composition: if you have g :: a -> b and f :: b -> c then f . g is essentially f(g(x)): first use g on an a to get a b and then use f on that b to get a c
<$> takes a function taking an a and returning a b, and a functor that contains an a, and it returns a functor that contains a b. So <$> is the same as fmap :: (a -> b) -> f a -> f b
<*> takes a functor that contains a function taking an a and returning a b, and a functor that contains an a, and it returns a functor that contains a b. So <*> kind of extract the function from a functor and applies it to an arguments also inside a functor, and finally returns the result into a functor
Note the explanations that you find in the book chapters are better than my attempt above
Maybe you learn via examples (like I do), so here are some simple ones you can mess around with in GHCI.
(.) - Function Composition
-- (.) :: (b -> c) -> (a -> b) -> a -> c
> f = (+1)
> g = (*2)
> a = f . g
> a 0
1 -- f( g( 0 ) ) or (0 * 2) + 1
> b = g . f
> b 0
2 -- g( f( 0 ) ) or (0 + 1) * 2
<$> - Functor
-- (<$>) :: Functor f => (a -> b) -> f a -> f b
> a = (*2)
> b = Just 4
> a <$> b
Just 8
<*> - Applicative
-- (<*>) :: Applicative f => f (a -> b) -> f a -> f b
> a = Just (*2)
> b = Just 4
> a <*> b
Just 8
I hope that helps.
The (.) operator composes functions. For example, \x -> f (g x) is the same as f . g. You can do this for arbitrary functions, e.g. \x -> f (g (h x)) equals f . g . h.
The <$> and <*> operators are not defined in terms of functionality. Their functionality depends on the actual type f that they are applied on. The <$> operator is an alternative for the fmap function in the Functor library. For example, for the Maybe type it takes the left operand and only applies it if the right operand is a Just value. So in order to find out what these operators do, just have a look at the implementations for the specific types.
I'm a a newbie to Haskell and sometimes Haskell type declarations confuse me, too.
It's easy to get lost at first because the tutorial says that the Capitalization naming convention is usually for type declaration and the camelCase naming convention is usually for variable.
Actually, this belongs to a higher technique in Haskell, may be polymorphism. Just think of f, a and b as some kind type variables - variables that handle type. And class in Haskell is not for Object like OOP but for type. So Functor f means that type f belongs to class Functor and so on.
If you replace these letter a, b, c with some type - called instance - for example String Int Char. It will make sense:
(.) :: (Int -> Char) -> (String -> Int) -> String -> Char
(<$>) :: Functor Maybe => (String -> Int) -> Maybe String -> Maybe Int -- type `Maybe` belongs to class `Functor`
...
While the common uses of <$> and <*> is obscured by the fact that they are in a typeclass, you can usually read the haddock documentation for this information. Use Hoogle if you have a hard time finding to which module a function belongs.
Related
Some Haskell source code (see ref):
-- | Sequential application.
--
-- A few functors support an implementation of '<*>' that is more
-- efficient than the default one.
(<*>) :: f (a -> b) -> f a -> f b
(<*>) = liftA2 id
-- | Lift a binary function to actions.
--
-- Some functors support an implementation of 'liftA2' that is more
-- efficient than the default one. In particular, if 'fmap' is an
-- expensive operation, it is likely better to use 'liftA2' than to
-- 'fmap' over the structure and then use '<*>'.
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x = (<*>) (fmap f x)
Three things seem to be quite confusing to me:
1) (<*>) is defined in terms of liftA2, where liftA2 is defined in terms of (<*>). How does it work? I see no obvious "recursion-break" case...
2) id is an a -> a function. Why is it passed into liftA2 as an (a -> b -> c) function?
3) fmap id x always equals x, since functors must preserve appropriate identities. Thus (<*>) (fmap id x) = (<*>) (x) where x = f a - an a-typed functor itself (by the way, how can a-typifying of the functor can be explained from the pure category theory's point of view? functor is just a mapping between categories, it has no further "typification"... seems like it is better to say - "a container of type a with an (endo)functor defined for each instance of asummed category Hask of well-defined Haskell types). So (<*>) (f a) while by definition (<*>) expects f(a' -> b'): thus, the only way to make it work is to deliberately bound a to be an (a' -> b'). However when I run :t \x -> (<*>) (fmap id x) in the gchi, it spits out something mind-blowing: f (a -> b) -> f a -> f b - which I fail to explain.
Can someone step by step explain how does that work and why it even compiles?
P.S. Category theory terms, if needed, are welcome.
For question 1, you left out a very important piece of context.
class Functor f => Applicative f where
{-# MINIMAL pure, ((<*>) | liftA2) #-}
Those definitions you quoted belong to a class. That means instances can override them. Furthermore, the MINIMAL pragma says that in order to work, at least one of them must be overridden in the instance. So the breaking of the recursion happens whenever one is overridden in a particular instance. This is just like how the Eq class defines (==) and (/=) in terms of each other so that you only need to provide a definition for one in a hand-written instance.
For question two, a -> b -> c is shorthand for a -> (b -> c). So it unifies with (let's rename variables to avoid collision) d -> d as (b -> c) -> (b ->c). (tangentially, that's also the type of ($).)
For three - you're absolutely right. Keep simplifying!
\x -> (<*>) (fmap id x)
\x -> (<*>) x
(<*>)
So it shouldn't really be a surprise ghci gave you the type of (<*>) back, should it?
1) (<*>) is defined in terms of liftA2, where liftA2 is defined in terms of (<*>). How does it work? I see no obvious "recursion-break" case...
It's not recursion. In your instance of Applicative you can either define both of them or just one. If you define just (<*>) then liftA2 is defined from (<*>), and vice versa.
2) id is an a -> a function. Why is it passed into liftA2 as an (a -> b -> c) function?
Unification works as follows,
(<*>) :: f (a -> b) -> f a -> f b
(<*>) = liftA2 id
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
id : u -> u
liftA2 : (a -> (b -> c) -> f a -> f b -> f c
------------------------------------------------------
u = a
u = b->c
id : (b->c) -> (b->c)
liftA2 : ((b->c) -> (b->c)) -> f (b->c) -> f b -> f c
------------------------------------------------------
liftA2 id : f (b->c) -> f b -> f c
3.
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 h x = (<*>) (fmap h x)
Renamed the first argument from f to h, to prevent confusion since f also shows in the type
h :: a -> (b -> c)
x :: f a
fmap :: (a -> d) -> f a -> f d
------------------------------
d = b -> c
h :: a -> (b->c)
x :: f a
fmap :: (a -> (b->c)) -> f a -> f (b->c)
----------------------------------------
fmap h x :: f (b -> c)
fmap h x :: f (b -> c)
(<*>) :: f (b -> c) -> f b -> f c
-------------------------------------
(<*>) fmap h x :: f b -> f c
Edit:
Consistency
To show the consistency of both formulas, first lets first rewrite liftA2 into something simpler. We can use the formula below to get rid of fmap and use only pure and <*>
fmap h x = pure h <*> x
and it's best to put all points in the definition. So we get,
liftA2 h u v
= (<*>) (fmap h u) v
= fmap h u <*> v
= pure h <*> u <*> v
So we want to check the consistency of,
u <*> v = liftA2 id u v
liftA2 h u v = pure h <*> u <*> v
For the first we need the property that pure id <*> u = u
u <*> v
= liftA2 id u v
= pure id <*> u <*> v
= u <*> v
For the second we need a property of liftA2. Properties of applicative are usually given in terms of pure and <*> so we need to derive it first. The required formula is derived from pure h <*> pure x = pure (h x).
liftA2 h (pure x) v
= pure h <*> pure x <*> v
= pure (h x) <*> v
= liftA2 (h x) v
This requires h : t -> a -> b -> c. The proof of consistency becomes,
liftA2 h u v
= pure h <*> u <*> v
= pure h `liftA2 id` u `liftA2 id` v
= liftA2 id (liftA2 id (pure h) u) v
= liftA2 id (liftA2 h u) v
= liftA2 h u v
1) (<*>) is defined in terms of liftA2, where liftA2 is defined in terms of (<*>). How does it work? I see no obvious "recursion-break" case...
Each instance is responsible for overriding at least one of the two. This is documented in a machine-readable way in the pragma at the top of the class:
{-# MINIMAL pure, ((<*>) | liftA2) #-}
This pragma announces that instance writers must define at least the pure function and at least one of the other two.
id is an a -> a function. Why is it passed into liftA2 as an (a -> b -> c) function?
If id :: a -> a, we can choose a ~ d -> e to get id :: (d -> e) -> d -> e. Traditionally, this particular specialization of id is spelled ($) -- maybe you've seen that one before!
3) ...
I don't... actually see any contradiction set up in the facts you state. So I'm not sure how to explain away the contradiction for you. However, you have a few infelicities in your notation that might be related to mistakes in your thinking, so let's talk about them briefly.
You write
Thus (<*>) (fmap id x) = (<*>) (x) where x = f a.
This is not quite right; the type of x is f a for some Functor f, but it is not necessarily equal to f a.
by the way, how can a-typifying of the functor can be explained from the pure category theory's point of view? functor is just a mapping between categories, it has no further "typification"... seems like it is better to say - "a container of type a with an (endo)functor defined for each instance of assumed category Hask of well-defined Haskell types
A functor constitutes two things: a mapping from objects to objects, and a mapping from arrows to arrows that is compatible with the object mapping. In a Haskell Functor instance declaration like
instance Functor F where fmap = fmapForF
the F is the mapping from objects to objects (objects in both the source and target categories are types, and F is a thing which takes a type and produces a type) and the fmapForF is the mapping from arrows to arrows.
I run :t \x -> (<*>) (fmap id x) in the gchi, it spits out something mind-blowing: f (a -> b) -> f a -> f b - which I fail to explain.
Well, you already observed that fmap id x = x, which means \x -> (<*>) (fmap id x) = \x -> (<*>) x. And for any function f, f = \x -> f x (up to some niggles that aren't important right now), so in particular \x -> (<*>) (fmap id x) = (<*>). So ghci gives you the type of (<*>), as it should.
Here I have to disagree with the GHC devs on their coding style :)
I would like to argue that one should never write
ap = liftA2 id
but, instead, use the equivalent
ap = liftA2 ($)
since the latter makes it clear that we are lifting the application operation.
(Actually, for very technical reasons GHC devs can not use $ here in this internal module, as pointed out below in the comments. So, at least they have a very good reason for their choice.)
Now, you might wonder why id can be used instead of $. Formally, we have
($) f x
= f x
= (id f) x
= id f x
hence, eta-contracting x then f, we get ($) = id.
Indeed, ($) is a "special case" of id.
id :: a -> a
-- choose a = (b -> c) as a special case
id :: (b -> c) -> (b -> c)
id :: (b -> c) -> b -> c
($):: (b -> c) -> b -> c
Hence, the main difference is: id is the identity on any type a, while ($) is the "identity" on any functional type b -> c. The latter is best visualized as a binary function (application), but it can equivalently be considered a unary function (identity) on a function type.
I am learning haskell and one of the tricky part are type variables.
Consider following example:
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
there is type variables a and b, they can be any type. And f is a type that has to be implemented a Functor.
Lets define a function for first argument for fmap:
Prelude> let replaceWithP = const 'p'
Now, I pass the function replaceWithP to fmap and looking at the type signature:
Prelude> :t fmap replaceWithP
fmap replaceWithP :: Functor f => f b -> f Char
Why does f a becomes to f b, why does it not stay a?
First, the type
fmap replaceWithP :: Functor f => f b -> f Char
is exactly equivalent to
fmap replaceWithP :: Functor f => f a -> f Char
because all type variables are implicitly universally quantified, so they can be renamed at will (this is known as alpha-conversion).
One might still wonder where the name b printed by GHC comes from. After all, fmap had f a in its type, so why did GHC choose to rename it as b?
The "culprit" here is replaceWithP
> :t const
const :: a -> b -> a
> let replaceWithP = const 'p'
> :t replaceWithP
replaceWithP :: b -> Char
So, b comes from the type of replaceWithP.
Type variables can be thought of normal variables, except you have types instead.
What does this mean? For instance, the variable a in C might be defined as:
int a = 2;
What are the possible values that you could have assigned a? The whole int range, because that's the set of values that a may take on. Let's take a look at this in pseudo-Haskell:
type b = Int
What are the set of values that b may take on? That's a trickier question. Typically we're used to seeing things such as 2, "hello", or True as values. However, in Haskell, we also allow types to be treated as values. Sort of. Let's say that b can take on any kind of form *. Essentially, this includes all types that do not need extra information for their construction:
data Tree a = Leaf a | Branch (Tree a) (Tree a)
Tree -- no, has kind: * -> *
Tree Int -- okay!
Int -- okay!
String -- okay!
This means that in your example:
fmap :: Functor f => (a -> b) -> f a -> f b
The variables a and b can be thought of variables that can take on types of any form provided that the type you decide to give it is within the appropriate range of type values (as restricted by kinds).
To more precisely answer your question now: why do we observe that:
fmap :: Functor f => (a -> b) -> f a -> f b
fmap replaceWithP :: Functor f => f b -> f Char
Let me rewrite the following equivalent definition, because variable naming can cause confusion:
fmap :: Functor f => (a -> b) -> f a -> f b
fmap replaceWithP :: Functor f => f z -> f Char
Hopefully this looks more clear now. When you supplied the replaceWithP :: x -> Char function, the following mappings occur:
-- Function types
fmap :: Functor f => (a -> b) -> f a -> f b
replaceWithP :: x -> Char
-- Type variable mappings
a -> x
b -> Char
What does this look like if we perform substitution?
Functor f => (x -> Char) -> f x -> f Char
After you have supplied in the replaceWithP function, you consume the first parameter, so you're left with:
fmap replaceWithP :: Functor f => f x -> f Char
Or equivalently:
fmap replaceWithP :: Functor f => f b -> f Char
I am reading in the haskellbook about applicative and trying to understand it.
In the book, the author mentioned:
So, with Applicative, we have a Monoid for our structure and function
application for our values!
How is monoid connected to applicative?
Remark: I don't own the book (yet), and IIRC, at least one of the authors is active on SO and should be able to answer this question. That being said, the idea behind a monoid (or rather a semigroup) is that you have a way to create another object from two objects in that monoid1:
mappend :: Monoid m => m -> m -> m
So how is Applicative a monoid? Well, it's a monoid in terms of its structure, as your quote says. That is, we start with an f something, continue with f anotherthing, and we get, you've guessed it a f resulthing:
amappend :: f (a -> b) -> f a -> f b
Before we continue, for a short, a very short time, let's forget that f has kind * -> *. What do we end up with?
amappend :: f -> f -> f
That's the "monodial structure" part. And that's the difference between Applicative and Functor in Haskell, since with Functor we don't have that property:
fmap :: (a -> b) -> f a -> f b
-- ^
-- no f here
That's also the reason we get into trouble if we try to use (+) or other functions with fmap only: after a single fmap we're stuck, unless we can somehow apply our new function in that new structure. Which brings us to the second part of your question:
So, with Applicative, we have [...] function application for our values!
Function application is ($). And if we have a look at <*>, we can immediately see that they are similar:
($) :: (a -> b) -> a -> b
(<*>) :: f (a -> b) -> f a -> f b
If we forget the f in (<*>), we just end up with ($). So (<*>) is just function application in the context of our structure:
increase :: Int -> Int
increase x = x + 1
five :: Int
five = 5
increaseA :: Applicative f => f (Int -> Int)
increaseA = pure increase
fiveA :: Applicative f => f Int
fiveA = pure 5
normalIncrease = increase $ five
applicativeIncrease = increaseA <*> fiveA
And that's, I guessed, what the author meant with "function application". We suddenly can take those functions that are hidden away in our structure and apply them on other values in our structure. And due to the monodial nature, we stay in that structure.
That being said, I personally would never call that monodial, since <*> does not operate on two arguments of the same type, and an applicative is missing the empty element.
1 For a real semigroup/monoid that operation should be associative, but that's not important here
Although this question got a great answer long ago, I would like to add a bit.
Take a look at the following class:
class Functor f => Monoidal f where
unit :: f ()
(**) :: f a -> f b -> f (a, b)
Before explaining why we need some Monoidal class for a question about Applicatives, let us first take a look at its laws, abiding by which gives us a monoid:
f a (x) is isomorphic to f ((), a) (unit ** x), which gives us the left identity. (** unit) :: f a -> f ((), a), fmap snd :: f ((), a) -> f a.
f a (x) is also isomorphic f (a, ()) (x ** unit), which gives us the right identity. (unit **) :: f a -> f (a, ()), fmap fst :: f (a, ()) -> f a.
f ((a, b), c) ((x ** y) ** z) is isomorphic to f (a, (b, c)) (x ** (y ** z)), which gives us the associativity. fmap assoc :: f ((a, b), c) -> f (a, (b, c)), fmap assoc' :: f (a, (b, c)) -> f ((a, b), c).
As you might have guessed, one can write down Applicative's methods with Monoidal's and the other way around:
unit = pure ()
f ** g = (,) <$> f <*> g = liftA2 (,) f g
pure x = const x <$> unit
f <*> g = uncurry id <$> (f ** g)
liftA2 f x y = uncurry f <$> (x ** y)
Moreover, one can prove that Monoidal and Applicative laws are telling us the same thing. I asked a question about this a while ago.
I have the applicative <$> operator more or less figured out, but I can't understand the signature I'm getting with the following example:
ghci> let f x y z = x + y + z -- f::Num a => a -> a -> a -> a
ghci> f <$> Just 2 <*> Just 3 <*> Just 4
Just 9
This result I understand, but when checking the following type:
ghci> :t (<$> f)
(<$> f) :: Num a => ((a -> a -> a) -> b) -> a -> b --This makes no sense to me
That signature I would understand as : a function that takes a (a -> a- > a) -> b function and an a as parameters and returns a b. According to this reasoning , I should call this like :
(<$>f) f 4
which would result in an Integer.
Obviously this is not true, so can you please help me understand how to read the type of (<$> f)?
a function that takes a (a -> a- > a) -> b function and an a as parameters and returns a b.
This is correct.
According to this reasoning , I should call this like :
(<$>f) f 4
which would result in an Integer.
No, because f does not have type (a -> a -> a) -> b or one compatible with it. Instead it has type Num a => a -> a -> a -> a. That is, f takes three numbers and produces a number, whereas we're looking for a function that takes a function (of type a -> a -> a) as its first argument.
<$> takes as a second argument something of type g b, where g is any applicative functor.
You are passing f :: Num a => a -> a -> a -> a as a second argument. Let's ignore the Num a context to keep things simple.
Hence, we look for g,b such that g b = a -> a -> a -> a.
Let's write the type of f in prefix form:
f :: (->) a ((->) a ((->) a a)) = g b
Hence, g = (->) a and b = ((->) a ((->) a a)). The latter is b = a -> a -> a in infix form.
It happens that (->) a is an applicative functor, so <$> f type checks. Note however that <$> is used on a completely different functor than the Maybe one you were using in your examples. Hence the confusion.
TL;DR: overloaded identifiers can shapeshift to many things adapting to their contexts, possibly in some unexpected way.
The type of fmap in Functor is:
fmap :: Functor f => (a -> b) -> f a -> f b
it looks like ,first apply function (a -> b) to the parameter of f a to create a result of type b, then apply f to it, and result is f b
using Maybe a for example:
fmap show (Just 1)
result is : Just "1"
same as saying:
Just (show 1)
but when (->) is used as a Functor (in Control.Monad.Instances)
import Control.Monad.Instances
(fmap show Just) 1
result is : "Just 1"
that is, Just is applied first, then show is applied. In another example ,result is same:
fmap (*3) (+100) 1
result is 303
why not *3 first, then +100?
The fmap instance for (->) r (i.e. functions) is literally just composition. From the source itself:
instance Functor ((->) r) where
fmap = (.)
So, in your example, we can just replace fmap with (.), and do some transformations
fmap (*3) (+100) 1 =>
(.) (*3) (+100) 1 =>
(*3) . (+100) $ 1 => -- put (.) infix
(*3) (1 + 100) => -- apply (+100)
(1 + 100) * 3 -- apply (*3)
That is, fmap for functions composes them right to left (exactly the same as (.), which is sensible because it is (.)).
To look at it another way (for (double) confirmation!), we can use the type signature:
-- general fmap
fmap :: Functor f => (a -> b) -> f a -> f b
-- specialised to the function functor (I've removed the last pair of brackets)
fmap :: (a -> b) -> (r -> a) -> r -> b
So first the value of type r (the third argument) needs to be transformed into a value of type a (by the r -> a function), so that the a -> b function can transform it into a value of type b (the result).
the type of fmap in Functor is:
fmap :: Functor f => (a -> b) -> f a -> f b
it looks like ,first apply function (a -> b) to the parameter of f a
to create a result of type b, then apply f to it, and result is f b
That is the type of fmap, but your interpretation of what that type means is wrong.
You seem to assume that f a has one parameter, and that that parameter has type a.
Consider xs :: [a]:
Perhaps xs = [].
Perhaps xs = [x1].
Perhaps xs = [x1, x2].
...
The type f a is a functor f with a single type parameter a. But values of type f a do not necessarily take the form F x, as you can see from the first and third cases above.
Now consider fmap f xs:
Perhaps fmap f xs = [].
Perhaps fmap f xs = [f x1].
Perhaps fmap f xs = [f x1, f x2].
...
We don't necessarily apply f at all (first case)! Or we might apply it more than once (third case).
What we do is replace the things of type a, with things of type b. But we leave the larger structure intact --- no new elements added, no elements removed, their order is left unchanged.
Now let's think about the functor (c ->). (Remember, a functor takes one type parameter only, so the input to (->) is fixed.)
Does a c -> a even contain an a? It might not contain any as at all, but it can somehow magic one out of thin air when we give it a c. But the result from fmap has type c -> b: we only have to provide a b out of that when we're presented with a c.
So we can say fmap f x = \y -> f (x y).
In this case, we're applying f on demand --- every time the function we return gets applied, f gets applied as well.
It needs to be defined that way to make the types work out. As you pointed out, the type of fmap is:
fmap :: Functor f => (a -> b) -> f a -> f b
Let's consider the case when the functor f is ((->) c)
(Note: we'd actually like to write this as (c ->), i.e. functions from c, but Haskell doesn't allow us to do this.)
Then f a is actually ((->) c a), which is equivalent to (c -> a), and similarly for f b, so we have:
fmap :: (a -> b) -> (c -> a) -> (c -> b)
i.e. we need to take two functions:
f :: a -> b
g :: c -> a
and construct a new function
h :: c -> b
But there's only one way to do that: you have to apply g first to get something of type a, and then apply f to get something of type b, which means that you have to define
instance Functor ((->) c) where
fmap f g = \x -> f (g x)
or, more succinctly,
instance Functor ((->) c) where
fmap = (.)
fmap for (->) is defined like fmap = (.).
So, (fmap f g) x is (f . g) x is f (g x). In your case (*3) ((+100) 1), which equals 3 * (100 + 1) which results in 303.
In order to form a function type, you need 2 kind parameters for (->), that is the single input argument type and the return type.
A Functor can only take 1 type parameter, so you have to nail down the input argument type(since it's the first one from left to right), which makes the return type of the function to be the type parameter of the Functor.
So for function (the Functor) a->b, you need to give fmap a function ff of type b->xxx other than a->xxx to work, and that means the function ff can only be applied after a->b is apply.