I'm reading through Chapter 25 (Composing Types) of the haskellbook, and wish to understand applicative composition more completely
The author provides a type to embody type composition:
newtype Compose f g a =
Compose { getCompose :: f (g a) }
deriving (Eq, Show)
and supplies the functor instance for this type:
instance (Functor f, Functor g) =>
Functor (Compose f g) where
fmap f (Compose fga) =
Compose $ (fmap . fmap) f fga
But the Applicative instance is left as an exercise to the reader:
instance (Applicative f, Applicative g) =>
Applicative (Compose f g) where
-- pure :: a -> Compose f g a
pure = Compose . pure . pure
-- (<*>) :: Compose f g (a -> b)
-- -> Compose f g a
-- -> Compose f g b
Compose fgf <*> Compose fgx = undefined
I can cheat and look the answer up online... The source for Data.Functor.Compose provides the applicative instance definition:
Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)
but I'm having trouble understanding what's going on here. According to type signatures, both f and x are wrapped up in two layers of applicative structure. The road block I seem to be hitting though is understanding what's going on with this bit: (<*>) <$> f. I will probably have follow up questions, but they probably depend on how that expression is evaluated. Is it saying "fmap <*> over f" or "apply <$> to f"?
Please help to arrive at an intuitive understanding of what's happening here.
Thanks! :)
Consider the expression a <$> b <*> c. It means take the function a, and map it over the functor b, which will yield a new functor, and then map that new functor over the functor c.
First, imagine that a is (\x y -> x + y), b is Just 3, and c is Just 5. a <$> b then evaluates to Just (\y -> 3 + y), and a <$> b <*> c then evaluates to Just 8.
(If what's before here doesn't make sense, then you should try to understand single layers of applicatives further before you try to understand multiple layers of them.)
Similarly, in your case, a is (<*>), b is f, and c is x. If you were to choose suitable values for f and x, you'd see that they can be easily evaluated as well (though be sure to keep your layers distinct; the (<*>) in your case belongs to the inner Applicative, whereas the <$> and <*> belong to the outer one).
Rather than <*>, you can define liftA2.
import Control.Applicative (Applicative (..))
newtype Compose f g a = Compose
{ getCompose :: f (g a) }
deriving Functor
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure a = Compose (pure (pure a))
-- liftA2 :: (a -> b -> c) -> Compose f g a -> Compose f g b -> Compose f g c
liftA2 f (Compose fga) (Compose fgb) = Compose _1
We have fga :: f (g a) and fgb :: f (g b) and we need _1 :: f (g c). Since f is applicative, we can combine those two values using liftA2:
liftA2 f (Compose fga) (Compose fgb) = Compose (liftA2 _2 fga fgb)
Now we need
_2 :: g a -> g b -> g c
Since g is also applicative, we can use its liftA2 as well:
liftA2 f (Compose fga) (Compose fgb) = Compose (liftA2 (liftA2 f) fga fgb)
This pattern of lifting liftA2 applications is useful for other things too. Generally speaking,
liftA2 . liftA2 :: (Applicative f, Applicative g) => (a -> b -> c) -> f (g a) -> f (g b) -> f (g c)
liftA2 . liftA2 . liftA2
:: (Applicative f, Applicative g, Applicative h)
=> (a -> b -> c) -> f (g (h a)) -> f (g (h b)) -> f (g (h c))
Related
fmap.fmap allows us to go "two layers deep" into a functor:
fmap.fmap :: (a -> b) -> f (g a) -> f (g b)
Is this also possible for applicative functors? Let's say I wanted to combine Just (+5) and [1,2,3] by using their applicative properties. I can think of an obvious way to do it, but it doesn't seem that trivial to me.
(<*>).(<*>) doesn't a have a conclusive type signature:
((<*>).(<*>)) :: (a1 -> a2 -> b) -> ((a1 -> a2) -> a1) -> (a1 -> a2) -> b
-- where I would expect something like:
-- ((<*>).(<*>)) :: f (g (a -> b)) -> f (g a) -> f (g b)
Is it possible to compose Just (+5) and [1,2,3] in this fashion?
EDIT:
The first step would be to go with either:
pure $ Just (+5) and fmap pure [1,2,3], or
fmap pure (Just (+5) and pure [1,2,3]
But I still don't how to compose these...
EDIT:
It would be nice to have a general way to compose a function f (g (a -> b) and f (g a), I'm not just looking for a solution for the above case, which is just supposed to serve as an example input of such a function. Basically I want a function:
(<***>) :: f (g (a -> b)) -> f (g a) -> f (g b)
liftA2 has a similar compositional property as fmap.
liftA2 f :: f a -> f b -> f c
(liftA2 . liftA2) f :: g (f a) -> g (f b) -> g (f c)
So you can write
(liftA2 . liftA2) ($) (pure (Just (+5))) (fmap pure [1,2,3]) :: [Maybe Integer]
i.e., (<***>) = (liftA2 . liftA2) ($). (much like (<*>) = liftA2 ($))
Another way to look at it is that the composition of applicative functors is an applicative functors, this is made concrete by Data.Functor.Compose:
{-# LANGUAGE ScopedTypeVariables, PartialTypeSignatures #-}
import Data.Functor.Compose
import Data.Coerce
(<***>) :: forall f g a b. (Applicative f, Applicative g)
=> f (g (a -> b)) -> f (g a) -> f (g b)
(<***>) = coerce ((<*>) :: Compose f g (a -> b) -> _)
The point with coerce is to show that (<***>) is the applicative (<*>) for the right type; we can also do the unwrapping manually
f <***> x = getCompose $ Compose f <*> Compose x
We have a f (g (a->b)). To get g a -> g b from g (a->b) we just need <*>, but g (a->b) is wrapped in f. Luckily f is a Functor so we can fmap over it.
Prelude> :t fmap (<*>)
fmap (<*>)
:: (Functor f1, Applicative f) =>
f1 (f (a -> b)) -> f1 (f a -> f b)
Prelude>
That's better, we have a function wrapped in a Functor now. If this Functor happens to be an Applicative, we can apply <*> through it.
Prelude> :t (<*>) . fmap (<*>)
(<*>) . fmap (<*>)
:: (Applicative f, Applicative f1) =>
f1 (f (a -> b)) -> f1 (f a) -> f1 (f b)
Prelude>
Just what the doctor ordered.
Prelude> let (<***>) = (<*>) . fmap (<*>)
Prelude> [Just (+2), Just (*3), Nothing] <***> [Just 7, Just 42, Nothing]
[Just 9,Just 44,Nothing,Just 21,Just 126,Nothing,Nothing,Nothing,Nothing]
Prelude>
The simple definition of function composition is:
f ( g x)
or
(f . g) $ x
Now I have following example:
newtype Compose f g a =
Compose { getCompose :: f (g a) }
deriving (Eq, Show)
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose fga) = Compose $ (fmap . fmap) f fga
Then I try to write fmap without composition operator as:
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose fga) = Compose $ fmap f (fmap f fga)
and the compiler complains:
* Couldn't match type `b' with `g b'
`b' is a rigid type variable bound by
the type signature for:
fmap :: forall a b. (a -> b) -> Compose f g a -> Compose f g b
at D:\haskell\chapter25\src\Twinplicative.hs:11:5
Expected type: f (g b)
Actual type: f b
* In the second argument of `($)', namely `fmap f (fmap f fga)'
In the expression: Compose $ fmap f (fmap f fga)
In an equation for `fmap':
fmap f (Compose fga) = Compose $ fmap f (fmap f fga)
* Relevant bindings include
fga :: f (g a)
(bound at D:\haskell\chapter25\src\Twinplicative.hs:11:21)
f :: a -> b
(bound at D:\haskell\chapter25\src\Twinplicative.hs:11:10)
fmap :: (a -> b) -> Compose f g a -> Compose f g b
(bound at D:\haskell\chapter25\src\Twinplicative.hs:11:5)
How to compose fmap above without composition operator?
The function you provide to the leftmost application of fmap should have type g a -> g b while you are providing f which has type a -> b. You can lift a function a -> b to g a -> g b using fmap i.e. fmap f. The second argument to the outer fmap should have type f (g a) which is the type of fga:
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose fga) = Compose $ fmap (fmap f) fga
I like Lee's answer, which states clearly how you could implement the Functor instance for Compose yourself from scratch. However, I also thought it worth answering a closely related question, which is: how do I start from the existing instance and mechanically rewrite it to avoid the (.) function composition? Therefore I tackle that question in this answer.
Since (f . g) x = f (g x) is the defining equation of (.), we conclude (fmap . fmap) f = fmap (fmap f). Applying both sides of the equation to fga, we get:
(fmap . fmap) f fga = fmap (fmap f) fga
The Typeclassopedia's Monad Transformers section explains:
Unfortunately, monads do not compose as nicely as applicative functors (yet another reason to use Applicative if you don’t need the full power that Monad provides)
Looking at the types of >>= and <*>, the above statement is not clear to me.
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Please explain the "monads do not compose as nicely as applicative functors."
I read this answer, but could you please give an example to help me understand?
There are several notions by which types of kind * -> * might "compose". The more important one is you can compose them "sequentially".
newtype Compose f g x = Compose { getCompose :: f (g x) }
Here you can see that Compose has kind (* -> *) -> (* -> *) -> (* -> *) much like any good composition of functors ought to.
So the question is: are there law-abiding instances like the following?
instance (Applicative f, Applicative g) => Applicative (Compose f g)
instance (Monad f, Monad g) => Monad (Compose f g)
And the short answer as to why monads don't compose as well as applicatives is that while the first instance can be written the second cannot. Let's try!
We can warm up with Functor
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose fgx) = Compose (fmap (fmap f) fgx)
Here we see that because we can fmap an fmap-ed f we can pass it through the layers f and g like we need to. A similar game is played with pure
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure a = Compose (pure (pure a))
and while (<*>) appears tricky, if you look carefully it's the exact same trick we used with both fmap and pure.
Compose fgf <*> Compose fgx = Compose ((<*>) <$> fgf <*> fgx)
In all cases, we can push the operators we need "through" the layers of f and g exactly as we might hope.
But now let's take a look at Monad. Instead of trying to define Monad via (>>=), I'm going to instead work via join. To implement Monad we need to implement
join :: Compose f g (Compose f g x) -> Compose f g x
using
join_f :: f (f x) -> f x -- and
join_g :: g (g x) -> g x
or, if we strip off the newtype noise, we need
join :: f (g (f (g x))) -> f (g x)
At this point it might be clear what the problem is---we only know how to join consecutive layers of fs or gs, but here we see them interwoven. What you'll find is that we need a commutativity property
class Commute f g where
commute :: g (f x) -> f (g x)
and now we can implement
instance (Monad f, Monad g, Commute f g) => Monad (Compose f g)
with (the newtype agnostic) join defined as
join :: f (g (f (g x))) -> f (g x)
join fgfgx = fgx where
ffggx :: f (f (g (g x)))
ffggx = fmap commute fgfgx
fggx :: f (g (g x))
fggx = join_f ffggx
fgx :: f (g x)
fgx = fmap join_g fggx
So what's the upshot of all this? Applicatives always Compose, but Monads Compose only when their layers Commute.
When can we commute layers? Here are some examples
instance Commute ((->) x) ((->) y) where
commute = flip
instance Commute ((,) x) ((,) y) where
commute (y, (x, a)) = (x, (y, a))
instance Commute ((->) x) ((,) y) where
commute (y, xa) = \x -> (y, xa x)
-- instance Commute ((,) x) ((->) y) does not exist; try to write yourself!
--
-- OR:
-- It turns out that you need to somehow "travel back in time" to make it
-- work...
--
-- instance Commute ((,) x) ((->) y) where
-- commute yxa = ( ..., \y -> let (x, a) = yxa y in a )
The Typeclassopedia's Monad Transformers section explains:
Unfortunately, monads do not compose as nicely as applicative functors (yet another reason to use Applicative if you don’t need the full power that Monad provides)
Looking at the types of >>= and <*>, the above statement is not clear to me.
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Please explain the "monads do not compose as nicely as applicative functors."
I read this answer, but could you please give an example to help me understand?
There are several notions by which types of kind * -> * might "compose". The more important one is you can compose them "sequentially".
newtype Compose f g x = Compose { getCompose :: f (g x) }
Here you can see that Compose has kind (* -> *) -> (* -> *) -> (* -> *) much like any good composition of functors ought to.
So the question is: are there law-abiding instances like the following?
instance (Applicative f, Applicative g) => Applicative (Compose f g)
instance (Monad f, Monad g) => Monad (Compose f g)
And the short answer as to why monads don't compose as well as applicatives is that while the first instance can be written the second cannot. Let's try!
We can warm up with Functor
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose fgx) = Compose (fmap (fmap f) fgx)
Here we see that because we can fmap an fmap-ed f we can pass it through the layers f and g like we need to. A similar game is played with pure
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure a = Compose (pure (pure a))
and while (<*>) appears tricky, if you look carefully it's the exact same trick we used with both fmap and pure.
Compose fgf <*> Compose fgx = Compose ((<*>) <$> fgf <*> fgx)
In all cases, we can push the operators we need "through" the layers of f and g exactly as we might hope.
But now let's take a look at Monad. Instead of trying to define Monad via (>>=), I'm going to instead work via join. To implement Monad we need to implement
join :: Compose f g (Compose f g x) -> Compose f g x
using
join_f :: f (f x) -> f x -- and
join_g :: g (g x) -> g x
or, if we strip off the newtype noise, we need
join :: f (g (f (g x))) -> f (g x)
At this point it might be clear what the problem is---we only know how to join consecutive layers of fs or gs, but here we see them interwoven. What you'll find is that we need a commutativity property
class Commute f g where
commute :: g (f x) -> f (g x)
and now we can implement
instance (Monad f, Monad g, Commute f g) => Monad (Compose f g)
with (the newtype agnostic) join defined as
join :: f (g (f (g x))) -> f (g x)
join fgfgx = fgx where
ffggx :: f (f (g (g x)))
ffggx = fmap commute fgfgx
fggx :: f (g (g x))
fggx = join_f ffggx
fgx :: f (g x)
fgx = fmap join_g fggx
So what's the upshot of all this? Applicatives always Compose, but Monads Compose only when their layers Commute.
When can we commute layers? Here are some examples
instance Commute ((->) x) ((->) y) where
commute = flip
instance Commute ((,) x) ((,) y) where
commute (y, (x, a)) = (x, (y, a))
instance Commute ((->) x) ((,) y) where
commute (y, xa) = \x -> (y, xa x)
-- instance Commute ((,) x) ((->) y) does not exist; try to write yourself!
--
-- OR:
-- It turns out that you need to somehow "travel back in time" to make it
-- work...
--
-- instance Commute ((,) x) ((->) y) where
-- commute yxa = ( ..., \y -> let (x, a) = yxa y in a )
Parse error in pattern: f . g
i am a beginner, where is wrong?
(f . g) x = f (g x)
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor g where
fmap :: (a -> b) -> f a -> f b
instance Functor F where
fmap id = id
fmap (f . g) = fmap f . fmap g
When you make an instance of Functor, you should prove the side condition that
fmap id = id
and
fmap (f . g) = fmap f . fmap g
(Technically the latter comes for free given the types involved and the former law, but it is still a good exercise.)
You can't do this just by saying
fmap id = id
but instead you use this as a reasoning tool -- once you have proven it.
That said, the code that you have written doesn't make sense for a number of reasons.
(f . g) x = f (g x)
Since this is indented, I'm somewhat unclear if this is intended to be a definition for (.), but that is already included in the Prelude, so you need not define it again.
class Functor f where
fmap :: (a -> b) -> f a -> f b
This definition is also provided for you in the Prelude.
class Functor g where
fmap :: (a -> b) -> f a -> f b
But then you define the class again, but here it has mangled the signature of fmap, which would have to be
fmap :: (a -> b) -> g a -> g b
But as you have another definition of Functor right above (and the Prelude has still another, you couldn't get that to compile)
Finally, your
instance Functor F where
fmap id = id
fmap (f . g) = fmap f . fmap g
makes up a name F for a type that you want to make into an instance of Functor, and then tries to give the laws as an implementation, which isn't how it works.
Let us take an example of how it should work.
Consider a very simple functor:
data Pair a = Pair a a
instance Functor Pair where
fmap f (Pair a b) = Pair (f a) (f b)
now, to prove fmap id = id, let us consider what fmap id and id do pointwise:
fmap id (Pair a b) = -- by definition
Pair (id a) (id b) = -- by beta reduction
Pair a (id b) = -- by beta reduction
Pair a b
id (Pair a b) = -- by definition
Pair a b
So, fmap id = id in this particular case.
Then you can check (though technically given the above, you don't have to) that fmap f . fmap g = fmap (f . g)
(fmap f . fmap g) (Pair a b) = -- definition of (.)
fmap f (fmap g (Pair a b)) = -- definition of fmap
fmap f (Pair (g a) (g b)) = -- definition of fmap
Pair (f (g a)) (f (g b))
fmap (f . g) (Pair a b) = -- definition of fmap
Pair ((f . g) a) ((f . g) b) = -- definition of (.)
Pair (f (g a)) ((f . g) b) = -- definition of (.)
Pair (f (g a)) (f (g b))
so fmap f . fmap g = fmap (f . g)
Now, you can make function composition into a functor.
class Functor f where
fmap :: (a -> b) -> f a -> f b
by partially applying the function arrow constructor.
Note that a -> b and (->) a b mean the same thing, so when we say
instance Functor ((->) e) where
the signature of fmap specializes to
fmap {- for (->) e -} :: (a -> b) -> (->) e a -> (->) e b
which once you have flipped the arrows around looks like
fmap {- for (->) e -} :: (a -> b) -> (e -> a) -> e -> b
but this is just the signature for function composition!
So
instance Functor ((->)e) where
fmap f g x = f (g x)
is a perfectly reasonable definition, or even
instance Functor ((->)e) where
fmap = (.)
and it actually shows up in Control.Monad.Instances.
So all you need to use it is
import Control.Monad.Instances
and you don't need to write any code to support this at all and you can use fmap as function composition as a special case, so for instance
fmap (+1) (*2) 3 =
((+1) . (*2)) 3 =
((+1) ((*2) 3)) =
((+1) (3 * 2)) =
3 * 2 + 1 =
7
Since . is not a data constructor you cannot use it for pattern matching I believe. As far as I can tell there isn't an easy way to do what you're trying, although I'm pretty new to Haskell as well.
let is not used for top-level bindings, just do:
f . g = \x -> f (g x)
But the complaint, as cobbal said, is about fmap (f . g), which isn't valid. Actually, that whole class Functor F where is screwy. The class is already declared, now I think you want to make and instance:
instance Functor F where
fmap SomeConstructorForF = ...
fmap OtherConstructorForF = ...
etc.