I'm a newbe in functional programming, and I'm trying to solve the following exercise;
Given the type
type Cont r a = (a -> r) -> r
Implement the following higher-order function
mapReader :: (a -> b) -> (Cont r a) -> Cont r b
The first step would be to simplify the types, which gives:
mapReader :: (a -> b) -> ((a -> r) -> r) -> (b -> r) -> r
Next, define the parameters that need to be provided in this function. These parameters are three functions so we get
mapReader :: (a -> b) -> ((a -> r) -> r) -> (b -> r) -> r
mapReader f g h = _1
From here, we can define the following types:
f :: a -> b
g :: (a -> r) -> r
h :: b -> r
_1 :: r
But now I'm stuck. There are two functions that result in r, and one of them contains another function (a -> r). How can I start defining r? Any hints are much appreciated!
We have
f :: a -> b
g :: (a -> r) -> r
h :: b -> r
and we need
_1 :: r
There are two ways we can make r: g and h.
Let's try using h. h takes an argument of type b. The only way to get one of those is using f. f takes an argument of type a, and ... we don't have any way to get one of those.
So now let's try using g instead:
mapReader f g h = g _2
We're told
_2 :: a -> r
Since we're constructing a function, we can apply lambda abstraction as usual:
mapReader f g h = g (\a -> _3)
a :: a
_3 :: r
But wait ... now we have an a, so we can go back to our first attempt:
mapReader f g h = g (\a -> h (f a))
Or, more compactly,
mapReader f g h = g (h . f)
What if instead of going back to the first attempt we did it the second way again?
mapReader' f g h =
g (\a1 -> g (\a2 -> _4))
_4 :: r
You could go this way forever, but you could also stop here in two different ways:
mapReader2 f g h =
g (\_ -> g (h . f))
mapReader3 f g h =
g (\a1 -> g (\_ -> h (f a1)))
Oy! These are three different functions that all have the same type, and as shown this approach can be used to generate an infinite family of functions! How can you decide which one you want? You have to consider the intention. g's argument is the continuation, so you want to compose a function with what you're passing g, not call g multiple times. So mapReader is the "correct" answer.
More precisely, mapReader is supposed to map morphisms for the continuation functor. That requires in particular that
mapReader id = id
That is,
mapReader id g h = g (h . id)
= g h
That's unconditionally true for the correct definition, but not for any of the others.
Start by looking at what you can do with the three arguments.
You can compose f and h: h . f :: a -> r.
You can apply g to h . f: g (h . f) :: r.
So you could simply say that mapReader f g h = g (h . f). There's not enough information here to specify what r is; it depends entirely on what
arguments g and h are given to mapReader.
So you have
f :: a -> b
h :: b -> r
g :: (a -> r) -> r
There's also the forward functional composition operator,
(>>>) :: (a -> b) -> (b -> r) -> (a -> r)
and the reversed application operator,
(&) :: t -> (t -> r) -> r
so that
f >>> h :: ......... -- what?
and
(f >>> h) & g :: ......... -- what else?
Can you come up with the definitions of (>>>) and (&), just from their types?
Let me get you started on the first one.
(>>>) :: (a -> b) -> (b -> r) -> (a -> r)
means that
(>>>) (f :: a -> b) :: (b -> r) -> (a -> r)
(>>>) (f :: a -> b) (g :: b -> r) :: (a -> r)
(>>>) (f :: a -> b) (g :: b -> r) (x :: a) :: r
So again we write them down
f :: a -> b
g :: b -> r
x :: a
f x :: b
g (f x) :: ....
And that's that.
The most important rule that we used here, is
x :: a
f :: a -> r
f x :: r
Related
In Learn you a Haskell, it is given that
fmap (+3) (*3)
is equivalent to
\x -> ((x*3)+3))
However, I can't understand why. Isn't it supposed to be \x -> ((x+3)*3)?
I don't know the implementation of fmap for (*3) functor, but my intuition tells me that since the functor (*3) is equivalent to \x -> x * 3, the map (+3) would be first applied and then (*3) be applied, but it is the other way around. What am I missing in here?
my intuition tells me that since the functor (*3) is equivalent to \x -> x * 3
Functions form a functor instance
instance Functor ((->) r) where ...
Those are the functions mapping from r.
Given a function g :: r -> a you can form a new function h :: r -> b with the help of f :: a -> b via h = fmap f g. It should now be clear that f :: a -> b cannot be applied first but must be applied second. That is h' = (g :: r -> a) . (f :: a -> b) does not make any sense but h = (f :: a -> b) . (g :: r -> a) does.
fmap has to obey two laws:
fmap id == id
fmap (f . g) == fmap f . fmap g
Your proposed definition, fmap' f g == g . f, satisfies the first law but violates the second law:
fmap' id f == f . id == f == id f -- OK
fmap' (f . g) h == h . (f . g)
== (h . f) . g
== (fmap' f h) . g
== fmap' g (fmap' f h)
== (fmap' g . fmap' f) h -- violation, since (.) is not commutative
The correct definition, fmap f g = f . h, satisfies both:
fmap id f == id . f == f == id f
fmap (f . g) h == (f . g) . h
== f . (g . h)
== fmap f (g . h)
== fmap f (fmap g h)
== (fmap f . fmap g) h
A "functor", in Haskell, is a higher order type, F, -- "higher order" meaning, it accepts another type variable, a (denoting any type whatever), -- such that we can have
F a fa
(a -> b) ab
-----------------
F b fmap ab fa
which is known as "flip fmap" (flip just means that the order of arguments is flipped, flip fmap fa ab == fmap ab fa). There are also some "common sense" laws it must follow.
For F ~ Maybe, say, it means
flip fmap :: Maybe a ->
(a -> b) ->
Maybe b
and for F ~ [],
flip fmap :: [] a ->
(a -> b) ->
[] b
which is more conventionally written as [a] -> (a -> b) -> [b].
In our case here, F a ~ r -> a, or more formally, F a ~ ((->) r) a, which means F ~ ((->) r),
flip fmap :: ((->) r) a ->
(a -> b) ->
((->) r) b
which is more conventionally written as (r -> a) -> (a -> b) -> (r -> b),
r -> a
a -> b
-------------
r -> b
which is the same as (r -> a) -> (a -> b) -> r -> b since with types, the arrows associate on the right, corresponding to the fact that applications associate on the left: f a b c is actually ((f a) b) c and
f a b c = d -- f a b c
f a b = \c -> d -- (f a b) c
f a = \b c -> d -- ((f a) b) c
f = \a b c -> d -- (((f) a) b) c
are all different ways to write down the same definition, and different ways to write down the same function call.
This then means we need to implement
fmap :: (a -> b) -> (r -> a) -> (r -> b)
fmap ab ra r = b
where
b =
So what could the definition be? Is it up to us to decode what goes where? Well, we must produce a b type value. The only thing we have that can do it for us, is ab :: a -> b.
Can we produce a b without it? Out of the blue? Except for erroring out, no, we can't -- we know nothing about that b type. It can be anything. So we're left with
b = ab a
a =
and now we must get an a somewhere, to use it as an argument to ab. Fortunately, ra can give it to us:
a = ra r
and r, we already got! So the types did write this implementation for us:
fmap :: (a -> b) -> (r -> a) -> (r -> b)
fmap ab ra r = b
where
b = ab a
a = ra r
or, simplifying and renaming, we get
fmap f g r = f ( g r)
= (f . g) r
by definition of the function composition, ., as
(.) :: (a -> b) -> (r -> a) -> (r -> b)
(f . g) r = f (g r)
which is a valid syntax definition, otherwise written as
(.) :: (a -> b) -> (r -> a) -> (r -> b)
(.) f g r = f (g r)
or
(.) :: (a -> b) -> (r -> a) -> (r -> b)
(.) f g = \ r -> f (g r)
or
(.) :: (a -> b) -> (r -> a) -> (r -> b)
(.) = \f g r -> f (g r)
All these are equivalent. And its type diagram
a -> b
r -> a
--------------
r -> b
As for the intuition, a functorial type value of type F A is, loosely, an F-type "something" than can somehow produce an A-type something, in some F-type sense.
The functor laws mean that F does so in some purely "structural", mechanical way, without regard to what that A value that it produces actually is. In other words, the A values do not influence how they are produced, only the F type itself determines that.
For example, Maybe Int could Maybe produce an Int. Or [Int] could produce several Ints. (*3) can also produce an Int, if we supply it with an Int argument.
What then this fmap is? What does it do? It transforms that would-be produced value. Every functor type must define its fmap, that is what makes it be a functorial type, that it defines the
instance Functor Maybe where
fmap ab (Just a) = (Just (ab a))
etc. So then, with functions r -> a, which produce that a type value promised by their type, after being applied to an argument, we transform that value by applying the transformation function to it:
fmap transf mult3 arg = tansf (mult3 arg)
which is just the definition of the functional composition itself, with arguments renamed.
So that's why, in this case,
fmap (+3) (*3) r = (+3) ((*3) r)
= (+3) (r*3)
= (r*3) + 3
we (+3) transform the value produced by (*3) in the ((->) r) sense, which is application to some user-supplied argument, r. So (*3) must be applied first, to get (it to produce) that value.
I'm having trouble understanding whats going on in this function. My understanding is that fmap f x returns a function that takes the last argument y. But when is y "fed" to fmap f x inside the case statement?.
func :: (Num a, Num b) => (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c
func f x y = case fmap f x of
Nothing -> Nothing
Just z -> fmap z y
For Maybe, the functor instance is defined as:
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just x) = Just (f x)
So for f ~ Maybe, fmap is specialized to fmap :: (g -> h) -> Maybe g -> Maybe h.
In your specific case, f has signature f :: a -> b -> c, or more verbose ff :: a -> (b -> c). So that means that for our signature of fmap, we obtain:
fmap :: (g -> h ) -> Maybe g -> Maybe h
f :: a -> (b -> c)
----------------------------------------------
g ~ a, h ~ (b -> c)
So that means fmap f x will have type fmap f x :: Maybe (b -> c). It is thus a Maybe that wraps a function of type b -> c.
Here we thus can inspect if fmap f x is a Just z, in which case z has type z :: b -> c, or Nothing.
In case it is a Just z, we thus can perform another fmap with z, and thus obtain a Maybe c.
Some playing around with functors and monads in ghci led me to a value whose type and behaviour I would like to understand better.
The type of \x -> join . x is (Monad m) => (a -> m (m b)) -> (a -> m b) and the type of \y -> y . (flip fmap) is (Functor f) => ((a -> b) -> f b) -> (f a -> c).
Version 8.2.2 of ghci permits the definition h = join . (flip fmap).
Why does h have type ((A -> B) -> A) -> (A -> B) -> B?
In particular, why do the functor and monad constraints disappear? Is this really the correct and expected behaviour? As a follow up, I would also like to ask:
Why does evaluating h (\f -> f u) (\x -> x + v) for integers u and v give u + 2v in every case?
In short: due to type deduction, Haskell knows that m and f are in fact a partially instantiated arrow.
Deriving the type
Well let us do the math. The function join . (flip fmap) is basically your given lambda expression \x -> join . x with as argument (flip fmap), so:
h = (\x -> join . x) (flip fmap)
Now the lambda expression has type:
(\x -> join . x) :: Monad m => (a -> m (m b)) -> (a -> m b)
Now the argument flip fmap has type:
flip fmap :: Functor f => f c -> ((c -> d) -> f d)
(we here use c and d instead of a and b to avoid confusion between two possibly different types).
So that means that the type of flip fmap is the same as the type of the argument of the lambda expression, hence we know that:
Monad m => a -> m (m b)
~ Functor f => f c -> ((c -> d) -> f d)
---------------------------------------
a ~ f c, m (m b) ~ ((c -> d) -> f d)
So we now know that a has the same type as f c (this is the meaning of the tilde ~).
But we have to do some extra computations:
Monad m => m (m b)
~ Functor f => ((c -> d) -> f d)
--------------------------------
m ~ (->) (c -> d), m b ~ f d
Hence we know that m is the same as (->) (c -> d) (basically this is a function where we know that input type, here (c -> d), and the output type is a type parameter of m.
So that means that m b ~ (c -> d) -> b ~ f d, so this means that f ~ (->) (c -> d) and b ~ d. An extra consequence is that since a ~ f c, we know that a ~ (c -> d) -> c
So to list what we derived:
f ~ m
m ~ (->) (c -> d)
b ~ d
a ~ (c -> d) -> c
So we now can "specialize" the types of both our lambda expression, and our flip fmap function:
(\x -> join . x)
:: (((c -> d) -> c) -> (c -> d) -> (c -> d) -> d) -> ((c -> d) -> c) -> (c -> d) -> d
flip fmap
:: ((c -> d) -> c) -> (c -> d) -> (c -> d) -> d
and type of flip fmap now perfectly matches with the type of the argument of the lambda expression. So the type of (\x -> join . x) (flip fmap) is the result type of the lambda expression type, and that is:
(\x -> join . x) (flip fmap)
:: ((c -> d) -> c) -> (c -> d) -> d
But now we of course did not yet obtained the implementation of this function. We are however already a step further.
Deriving the implementation
Since we now know that m ~ (->) (c -> d), we know we should lookup the arrow instance of a monad:
instance Monad ((->) r) where
f >>= k = \ r -> k (f r) r
So for a given function f :: r -> a, as left operand, and a function k :: a -> (r -> b) ~ a -> r -> b as operand, we construct a new function that maps a variable x to k applied to f applied to x, and x. It is thus a way to perform some sort of preprocessing on an input variable x, and then do the processing both taking into account the preprocessing and the original view (well this is an interpretation a human reader can use).
Now join :: Monad m => m (m a) -> m a is implemented as:
join :: Monad m => m (m a) -> m a
join x = x >>= id
So for the (->) r monad, this means that we implement this as:
-- specialized for `m ~ (->) a
join f = \r -> id (f r) r
Since id :: a -> a (the identity function) returns its argument, we can further simplify it to:
-- specialized for `m ~ (->) a
join f = \r -> (f r) r
or cleaner:
-- specialized for `m ~ (->) a
join f x = f x x
So it basically is given a function f, and will then apply an argument twice to that function.
Furthermore we know that the Functor instance for the arrow type is defined as:
instance Functor ((->) r) where
fmap = (.)
So it is basically used as a "post processor" on the result of the function: we construct a new function that will do the post processing with the given function.
So now that we specialized the function enough for the given Functor/Monad, we can derive the implementation as:
-- alternative implementation
h = (.) (\f x -> f x x) (flip (.))
or by using more lambda expressions:
h = \a -> (\f x -> f x x) ((flip (.)) a)
which we can now further specialize as:
h = \a -> (\f x -> f x x) ((\y z -> z . y) a)
-- apply a in the lambda expression
h = \a -> (\f x -> f x x) (\z -> z . a)
-- apply (\z -> z . a) in the first lambda expression
h = \a -> (\x -> (\z -> z . a) x x)
-- cleaning syntax
h a = (\x -> (\z -> z . a) x x)
-- cleaning syntax
h a x = (\z -> z . a) x x
-- apply lambda expression
h a x = (x . a) x
-- remove the (.) part
h a x = x (a x)
So h basically takes two arguments: a and x, it then performs function application with a as function and x as parameter, and the output is passed to the x function again.
Sample usage
As sample usage you use:
h (\f -> f u) (\x -> x + v)
or nicer:
h (\f -> f u) (+v)
so we can analyze this like:
h (\f -> f u) (+v)
-> (+v) ((\f -> f u) (+v))
-> (+v) ((+v) u)
-> (+v) (u+v)
-> ((u+v)+v)
So we add u+v to v.
Types line up easier with >>>:
a -> b >>>
b -> c ::
a -> c
Here, we have
join . flip fmap == flip fmap >>> join
flip fmap :: Functor f => f a -> ((a -> b) -> f b )
join :: Monad m => (m (m b)) -> m b
----------------------------------------------------------
flip fmap >>> join ::
(Functor f, Monad m) => f a -> m b , ((a -> b) ->) ~ m, f ~ m
::
(Functor f, Monad f) => f a -> f b , f ~ ((a -> b) ->)
:: ((a -> b) -> a) -> ((a -> b) -> b)
Simple, mechanical, mundane.
To see what it does, combinatory style definitions are usually easiest to twiddle with,
(join . flip fmap) f g x =
join (flip fmap f) g x = -- join f x = f x x
(`fmap` f) g g x = -- f `fmap` g = f . g
(g . f) g x
g (f g) x
So we don't need x after all (or do we?). The join and fmap definitions for functions are given in the margins. We've arrived at
(join . flip fmap) f g = g (f g) -- f :: (a -> b) -> a, g :: a -> b
-- f g :: a , g (f g) :: b
Another way is starting from the types, going by the rule of modus ponens,
((a -> b) -> a) (a -> b) -- f g
---------------------------
(a -> b) a -- g (f g)
---------------------------------------
b
According to the tutorial on Lenses:
type Getting b a b = (b -> Const b b) -> (a -> Const b a)
-- ... equivalent to: (b -> b ) -> (a -> b )
-- ... equivalent to: (a -> b )
Question: Why is (b -> b) -> (a -> b) equivalent to (a -> b)?
The tutorial isn't very precise about this. Here's the full definition of Getting:
type Getting r s a = (a -> Const r a) -> s -> Const r s
Stripping off the newtype noise,
Getting r s a ~= (a -> r) -> s -> r
The interesting isomorphism you should get from this is the following:
(forall r. Getting r s a) ~= s -> a
In a now-deleted comment, chi pointed out that this is a special case of the Yoneda lemma.
The isomorphism is witnessed by
fromGetting :: Getting a s a -> (s -> a)
fromGetting g = getConst . g Const
-- ~= g id
-- Note that the type of fromGetting is a harmless generalization of
-- fromGetting :: (forall r. Getting r s a) -> (s -> a)
toGetting :: (s -> a) -> Getting r s a
toGetting f g = Const . getConst . g . f
-- ~= g . f
-- Note that you can read the signature of toGetting as
-- toGetting :: (s -> a) -> (forall r. Getting r s a)
Neither fromGetting nor toGetting has a rank-2 type, but to describe the isomorphism, the forall is essential. Why is this an isomorphism?.
One side is easy: ignoring the Const noise,
fromGetting (toGetting f)
= toGetting f id
= id . f
= f
The other side is trickier.
toGetting (fromGetting f)
= toGetting (f id)
= \g -> toGetting (f id) g
= \g -> g . f id
Why is this equivalent to f? The forall is the key here:
f :: forall r. Getting r s a
-- forall r. (a -> r) -> s -> r
f has no way to produce an r except by applying the passed function (let's call it p) to a value of type a. It's given nothing but p and a value of type s. So f really can't do anything except extract an a from the s and apply p to the result. That is, f p must "factor" into the composition of two functions:
f p = p . h
So
g . f id = g . (id . h) = g . h = f g
The type says "You give me a b -> b and an a, and I'll give you a b." What can a function with that type do with its b -> b? Two options:
Ignore the function altogether
Apply it to a b
How do you get hold of a b to apply the function to? You use the a to produce one. So either way, it has to do the work of an a -> b.
Here's some code to witness the (edit: not-quite) isomorphism.
in :: ((b -> b) -> a -> b) -> (a -> b)
in f x = f id x
out :: (a -> b) -> ((b -> b) -> a -> b)
out f g x = g (f x)
It is not clear to me why the function defined as
f g x = g . g x
has the type
f :: (b -> a -> b) -> b -> a -> a -> b
I would have thought it would be of type
f :: (t -> t) -> t -> t
Can anyone explain to me how the expression is broken down? Thanks!
Note that function application has the highest priority; operators come later.
So, the term g . g x first applies g to x, and then composes the result and g itself. If x has type b, g must have type b -> c. Since we compose g with g x (the latter of type c), c must be a function type returning b, so c = a -> b. Now, the type of g is b -> a -> b and the type of g . g x is a -> (a -> b); the type of f happens to be (b -> a -> b) -> b -> a -> a -> b.
If you wanted something like (a -> a) -> a -> a instead, you could try one of this
f g x = g (g x)
f g x = (g . g) x
f g x = g . g $ x
f g = g . g
The idea is about understanding the (.) operator, it has a type of
(.) :: (b -> c) -> (a -> b) -> a -> c
It takes two functions each with one parameter and compose them, after applying g x the compiler assumed g is actually g :: a -> b -> c in order to satisfy the signature of (.) :: (b -> c) -> (a -> b) -> a -> c which takes two functions with one argument. Otherwise the code won't compile.
And finally if you want the signature f :: (t -> t) -> t -> t you need something like this:
λ> let applyTwice g = g.g
λ> :t applyTwice
applyTwice :: (a -> a) -> a -> a
λ> applyTwice (*2) 3
12