Reputation: 31
I know the title is a bit unclear, the problem is:
Suppose I have a function of type a -> c
, another function of type b -> d
, how can I get a function of type (a -> b) -> (c -> d)
, or is it impossible in general?
Probably I should provide some background. I asked this question because I have difficulty solving Exercise 9 from the paper Fun with phantom types.
data Type t where
...
RFun :: Type a -> Type b -> Type (a -> b)
And the tequal
function
tequal :: Type t -> Type u -> Maybe (t -> u)
...
tequal (RFun a b) (RFun c d) = -- should do something with (tequal a c) (tequal b d)
So the problem boils down to composing a -> c
and b -> d
to get (a -> b) -> (c -> d)
Upvotes: 3
Views: 147
Reputation: 15605
As a small supplement to max taldykin's answer,
Given
f :: (a -> c) -> (b -> d) -> (a -> b) -> (c -> d)
f ac bd ab = ???
there's really only one way to combine the arguments
bd . ab :: a -> d
but now we're stuck! We have no way to construct a c -> d
from any combination of a -> c
, b -> d
, a -> b
, or a -> d
.
On the other hand, if we had a c -> a
then we could construct a
f :: (c -> a) -> (b -> d) -> (a -> b) -> (c -> d)
f ca bd ab = bd . ab . ca
By the way, it can be very helpful to get out a pen and paper and draw some arrows and try to connect them into a diagram:
If you try to do the same for f :: (a -> c) -> (b -> d) -> (a -> b) -> (c -> d)
then you'll see that there's no way to draw a diagram that connects c -> d
:
and now we have no way to connect the dots.
Upvotes: 3
Reputation: 12898
This is impossible.
Suppose you have desired function f :: (a -> b) -> (c -> d)
.
You can simplify it's type to (a -> b) -> c -> d
(See why).
How could implementation of f
look like? It has first argument of type a -> b
and second of type c
:
f ab c = ...
What can you do with ab
? It's a function but you can't apply it because you don't have anything of type a
(except _|_
). And even if you have functions g :: a -> c
and h :: b -> d
they are of no use because you don't have anything of type a
or b
and you can't compose them.
So the only valid implementation is something like
f ab = undefined
or
f = undefined
Regarding second part of your question, it seems that you can recursively use tequal
to check function type equality: types a -> c
and b -> d
are equal only if a
= b
and c
= d
(this is valid because toy type system from the paper don't have type variables).
Here is a sketch of implementation:
tequal (RFun a c) (RFun b d)
= liftM2 func (tequal a b) (tequal c d)
You can note that the code is almost identical to the case for RPair
. This is somehow related to currying.
Upvotes: 3
Reputation: 619
I believe that you are looking for Higher Order Functions, which is basically a function taking functions as parameters or returning other functions.
For example to illustrate a higher order function, you can define the following functions:
f0 :: Int -> Int
f0 x = 0
f1 :: a -> a
f1 x = x
f2 :: (a -> a) -> a -> a
f2 f a = f(a)
f3 :: (a -> a) -> (a -> a)
f3 f = f1
Notice that f2 takes a function and apply it to the second parameter and that f3 takes a function and return the function f1.
If you execute f2(f3(f0)) 5, it is going to return 5 to you.
Step-by-step
1- f2(f3(f0)) 5 f3 takes a function (f0) and will return f1.
2- f2(f1) 5 f2 takes a function (f1) and applies it to the second parameter (5)
3- f1(5) f1 is applied to 5.
Upvotes: 0