Haskell Higher order function Type - haskell

I am studying haskell now.
But I am struggling with 'Type'.
For example,
type of f function is
f g (x,y)= g x y
(a -> b -> c) -> (a, b) -> c
type of the following Haskell function h
h f g x y = f (g x y) x
(a -> b -> c) -> (b -> d -> a) -> b -> d -> c
How can I understand how to guess type of function?

I'll walk you through the first one: hopefully this gives you enough of an idea that you can figure out the second one by yourself.
So the function definition is:
f g (x,y)= g x y
f is the function we're interested in, and we can see from the above - just from the left hand side in fact - that it takes 2 arguments: g and the tuple (x,y). So let's use some type variables:
we'll use a for the type of g
b for the type of x
c for the type of y
and d for the type that f outputs when given the two arguments.
This gives us
f :: a -> (b, c) -> d
and further that is all the information that we can get from the left of the =. We can learn more by looking at the right hand side - the g x y which must be of type d.
Well the expression g x y itself tells us that g is a function which can take 2 arguments. And further we have already assigned types to those arguments - and to its return value (since this is the same value that f g (x,y) outputs, which we already said has type d).
Writing it all out, we find that the type of g is simply b -> c -> d. Substituting that in the type of f which we wrote down above, we get:
f :: (b -> c -> d) -> (b, c) -> d
If we cared, we could rename the type variables now so that this matches the signature you were given - but hopefully you can see that they're the same without having to do that.
As I said, although slightly more involved, the second exercise can be solved using exactly the same logic.

Related

Implementing a Haskell function from a signature

Im trying to wrap my head around Haskell and I'm having trouble trying to implement the following signature as a function. Could you guys give me an example using lambda expressions?
(b -> c) -> (a -> b) -> a -> c
Try with simpler examples first. For example,
f :: a -> a
f = ...
Since f is a function of one argument, we can extend this without thinking much into:
f :: a -> a
f = \x -> ...
Picking a return value for this function, we have exactly one good candidate, x, so:
f :: a -> a
f = \x -> x
although we could also have picked undefined or error "meh", or f x, which are less useful.
Here's another simple example:
g :: (a, b) -> (b, a)
g = ...
The only pattern that matches the function's input is a pair, so:
g :: (a, b) -> (b, a)
g = \(x, y) -> ...
This doesn't have to be equivalent to swap, but it's a good candidate because it terminates.
A last example that is more complicated:
h :: ((a, b) -> c) -> a -> b -> c
h = ...
This is a function of three arguments of types (a, b) -> c, a and b, so without thinking much we can extend the answer partially:
h :: ((a, b) -> c) -> a -> b -> c
h = \f -> \x -> \y -> ...
h = \f x y -> ...
(The lower line is just a convenient way to stack curried arguments.)
Now, I gave them names f, x and y because I think f is a good, generic name for a value that contains an ->, and x and y are good, generic names for arbitrary values. I could also have picked a and b to strengthen the connection between the types of the same name, but it'd also be a little confusing. So here, x :: a and y :: b.
As for filling out the function body, I can either go by asking "How do I apply the things I've got so the types align", or I can look at the return type, c, and look at what I have available to make a value of type c. f returns c if I feed it a pair of type (a, b). I have an x :: a and a y :: b, so (x, y) :: (a, b):
h :: ((a, b) -> c) -> a -> b -> c
h = \f x y -> f (x, y)
This is incidentally curry. I don't think you can find any other solution that terminates?
For simple functions there is often only one good candidate. When you have type signatures with multiple values of the same type, you have to consider what happens if you pick one over the other. The first case I can think of is when you implement the >>= operator for the state monad.
Let's rename our type variables:
a becomes oil
b becomes petrol
c becomes co₂
Now, you already recognised what the arguments to your function are:
implementation (x :: petrol -> co₂)
(y :: oil -> petrol)
(z :: oil)
= (? :: co₂)
It's sort of conventional to name functions f, g... and values a, b... _if we know nothing about the underlying types. Ok, but after we named the types, let's pick appropriate names accordingly:
implementation (car :: petrol -> co₂)
(refinery :: oil -> petrol)
(tankship :: oil)
= (? :: co₂)
Or, in lambda form without the local signatures:
implementation = \car refinery tankship -> ?
I'll leave the rest to you.

How do I determine type of Haskell functions? [duplicate]

This question already has an answer here:
Type Inference in Haskell for functions
(1 answer)
Closed 3 years ago.
I'm preparing for my exams but there is something I can't understand.
functions:
tw f x = f (f x)
f x y = (y, x)
I am able to determine the type of 'f' which is
f :: t1 -> t -> (t, t1)
but can't determine the type of 'tw'.
Supposed type of tw:
tw :: (t -> t) -> t -> t
thanks!
Let us analyze the function tw:
tw f x = f (f x)
tw takes as parameters f and x. At the moment we dot not know much about these parameters, so we will give these as types f :: a and x :: b.
Now we see a function application with f the function and x the parameter. This thus means that f is a function that takes a value of type b (the type of x), and returns something. We thus specify that f has as type f :: b -> c, with c a new type variable we introduce. We thus know that f x :: c.
We furthermore see, that there is a function application with f :: b -> c the function, and f x :: c the parameter. Since the type of the parameter of f is b, and f x has as type c. We thus come to the conclusion, that b and c must be the same type.
This thus means that we derived as types:
x :: b
f :: b -> b
We can furthermore analyze the type of tw f x by determining the type of f (f x). Since f x has type f x :: b, and f has type f :: b -> b, we know that f (f x) has type f (f x) :: b. So that means that the type for tw is:
tw :: (b -> b) -> b -> b
If we substitute b for t, then we obtain the expected type signature. But since b and t are just variables, that does not matter much.

Clarification on a Haskell function type argument

On a recent worksheet I was asked to explain why the function f, in: f g x = g (g x) x has no type.
I'm quite new to Haskell and I'm quite confused by how could one work out the association orders of the left and right expressions without knowing any details about the functions. It seems like that g should be defined as:
g :: a -> b, supposing that the type of x was a - however that seems to lead to trouble immediately as on the RHS, g (g x) x seems to imply g takes 2 arguments, one of type b and one of type a. Moreover I'm also stuck as to how to read the LHS also, i.e. does f take in 2 arguments: a function g and a variable x or does it take in simply 1 argument, (g x)?
I'm wondering if anyone could enlighten me as to how these expressions should be read?
To be able to answer questions like this, you need to think like the Haskell compiler. We have a function.
f g x = g (g x) x
In order for this to be well-typed, we need to find the types for f, g, and x. Now, f takes two arguments, so
f :: a -> b -> c
g :: a
x :: b
We also know that g x must make sense as an expression (we would say that g x is "well formed"), so g must be a function to which x can be applied. So it is also the case that
g :: b -> t0
Where t0 is a type variable, for now. We don't know the result of g x; we just know that it "makes sense". Now, the outer g (g x) x must also make sense. So g has to be a type which we can apply g x (which has type t0, as we said before) and x (which has type b) to be able to get a result of type c (the return type of the function). So
g :: t0 -> b -> c
Now, here's where the problem happens. We see that g has three declarations: a, b -> t0, and t0 -> b -> c. In order for g to have all three of these types, they must unify. That is, they have to be able to become the same, by plugging in values for certain variables. The a poses no problems, seeing as it's a free variable and doesn't depend on anything else, so we can "set" it to whatever we want. So b -> t0 and t0 -> b -> c have to be the same. In Haskell, we write that as
(b -> t0) ~ (t0 -> b -> c)
Parentheses (in types) are right-associative, so this is equivalent to
(b -> t0) ~ (t0 -> (b -> c))
In order for two function types to be the same, their arguments must be the same, so
b ~ t0
t0 ~ (b -> c)
By the transitive property, this implies that
b ~ (b -> c)
So b is a type which takes itself as an argument. This is what Haskell calls an infinite type and is inadmissible by the current standard. So in order for that function you've written to be acceptable, b must be a type which does not exist in Haskell. Therefore, f is not a valid Haskell function.
The relevant rules are:
Application is written as juxtaposition, i.e., f x applies f to x.
Parentheses are used to delimit expressions, not for function application, i.e., f (g x) applies f to g x. (Where g x is itself the application of g to x.)
Application associates to the left, i.e., f x y = (f x) y.
Putting these together, we can see that g (g x) x = (g (g x)) x, i.e., the application of g (g x) to x, where g (g x) is itself the application of g to g x.
I should also mention that all functions in Haskell take exactly one argument. Where it appears that a function takes multiple arguments, there is really currying:
f x y z = ((f x) y) z
In other words, f is a function that takes an argument and returns a function that takes an argument and returns a function that takes an argument and returns a value. You can probably see why we sometimes prefer to lie a bit and say that a function takes multiple arguments, but it is not technically true. A function that "takes multiple arguments" is really a function that returns a function, which may return a function, and so on.
Function application is left associative: a b c parses as (a b) c
Function definitions are syntactic sugar for lambda expressions: f x y = ... means f = \x y -> ...
Lambdas with multiple arguments are curried automatically: \x y -> ... means \x -> (\y -> ...)
Thus
f g x = g (g x) x
means
f = \g -> (\x -> (g (g x)) x)
Now let's try to derive the type of f. Let's give it a name:
f :: ta
But what exactly is ta? f is defined as a lambda, so its type involves -> (it's a function):
\g -> (\x -> (g (g x)) x) :: tb -> tc
g :: tb
\x -> (g (g x)) x :: tc
I.e. the type of \g -> ... is tb -> tc for some types tb and tc, and the type of g (the argument) is tb, and the type of the result (the function body) is tc.
And since the whole thing is bound to f, we have
ta = tb -> tc
We're not done with tc, though:
\x -> (g (g x)) x :: td -> te
x :: td
(g (g x)) x :: te
with
tc = td -> te
The function body (whose type we've called te) consists of an application of (what must be) a function to the variable x. From this it follows that:
g (g x) :: td -> te
because
x :: td
(g (g x)) x :: te
Drilling down again, we have
g :: tf -> (td -> te)
g x :: tf
because applying g to g x must have type td -> te. Finally,
g :: td -> tf
because
x :: td
g x :: tf
Now we have two equations for g:
g :: tf -> (td -> te)
g :: td -> tf
Therefore
tf = td
td -> te = tf
tf -> te = tf
Here we run into a problem: tf is defined in terms of itself, giving something like
tf = (((((... -> te) -> te) -> te) -> te) -> te) -> te
i.e. an infinitely large type. This is not allowed, and that's why f has no valid type.

Calculating types of Haskell Functions

Having troubles with manually calculating types of given functions in Haskell for an exam at the weekend.
I understand the basics such as:
i x = x :: t -> t
k x y = x :: t -> t1 -> t
But having trouble on more complicated questions such as:
two f x = f (f x)
s x y z = x z (y z)
Any explanations would be much appreciated!
In those two examples the only hints you have as to the types of the functions come from observing the application going on. In Haskell application hardly has any syntax, so I'll rewrite them a bit more obviously.
two f x = f(f(x))
s x y z = x(z)(y(z))
We'll now discover the types of these functions through gradual refinement. For instance, beginning with two we know that it takes in two arguments and thus must have a type which agrees with the (more general) type
two :: a -> b -> c
We also know that the a type variable above actually corresponds to a function because f is being applied to both x and f(x).
two :: (a -> b) -> c -> d
Since f is applied to x we know that here a and c must be the same.
two :: (a -> b) -> a -> d
and since we apply f again to its result f(x) we know that the result type must be the same as the input type
two :: (a -> a) -> a -> b
And finally, the result of calling f is the total result of two so d must also equal a
two :: (a -> a) -> a -> a
This uses all of the information we have in the definition and is the most general type that is compatible with the definition of two.
We can do basically the same process for s. We know it has 3 arguments
s :: a -> b -> c -> d
We know that the first and second arguments are functions of some kind. We see the second argument applied to a single value and the first applied to two values.
s :: (a -> b -> c) -> (d -> e) -> f -> g
We also know that the first input to both functions are the same (namely, it's z each time). This lets us infer that a, d, and f are the same type
s :: (a -> b -> c) -> (a -> d) -> a -> e
We also know that the result of calling the second function is the second argument to the first function, so b and d must be the same.
s :: (a -> b -> c) -> (a -> b) -> a -> e
Finally, the result of fully applying the first function is the final result of s so c and e are the same
s :: (a -> b -> c) -> (a -> b) -> a -> c
While that might be a lot to digest and kind of a blur, the thing to emphasize is that the tools I've used to solve this problem are all primitive. Effectively, I introduce arrows (->) when I see that the type got applied to some values and thus must be a function of a certain number of arguments and I unify type variables by following the values through their expression. These are sufficient tools for inferring the types of simple functions like two and s.
Your two and s are what as known as higher level functions, because they take functions as arguments. You already have the tools to discern their types, you just have to be willing to be a bit more abstract about it.
If you're given the expression
f x
You know the type of f is a -> b with x :: a and f x :: b. If you see
f (f x)
Then you can deduce that the output type of (f x) is the same as the input type for f. This means that a ~ b, so f :: a -> a and x :: a. If we look at the type of two, we can deduce that it follows the pattern
two :: s -> t -> u
but the first argument to two is f, which has the type a -> a, so we can plug that in as
two :: (a -> a) -> t -> u
And x is the second argument with type a, so we can plug that in
two :: (a -> a) -> a -> u
And the return type is the same as the return type of f (f x), which has the return type of f, which has the return type of a, so if we plug that in we get the final type
two :: (a -> a) -> a -> a
For s, we can do similarly. We start off by saying s follows the form
s :: s -> t -> u -> v
since it has 3 arguments. The expression (y z) is function application, so y must have the type y :: a -> b, with z :: a. Plugging that in to s:
s :: s -> (a -> b) -> a -> v
Then we look at x z (y z). Since y z :: b and z :: a, x is a function of two arguments, the first of type a and the second of type b, with some unknown return type c, so we can plug that in as
s :: (a -> b -> c) -> (a -> b) -> a -> c
Let's look at
two f x = f (f x)
We will proceed by writing down what we know, using variables for anything we don't. Some of the things we know will be equations, and like in math, we will substitute around in the equations until we get something that we can't do anything else with.
Starting with the expression f x. f is a function, and its argument type is whatever x's type is, so:
x :: a -- a is a new variable
f :: a -> b -- b is a new variable
These two equations say exactly what I just said in the previous sentence. Also, we created the variable b which is the type of the result of the application:
f x :: b
Now let's move on to f (f x). So the argument type of f has to be the type of f x, which we know is b, so:
f :: b -> c -- c is a new variable
f (f x) :: c
But, of course, a function can only have one type, and we already have a type for f:
f :: a -> b -- from above
That means that
a = b
b = c
We've reached the top level expression now. So now let's look at the types of the input variables we've found together with the expression:
f :: a -> b
x :: a
f (f x) :: c
Now we go substituting around as much as we can, expressing it with as few variables as possible (but only using equalities that we have deduced). We'll try to do it all in terms of a.
f :: a -> b
= a -> a -- because b = a
x :: a
f (f x) :: c
= b -- because c = b
= a -- because b = a
And there we have it:
two :: (a -> a) -> a -> a
^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^
type of f type of x type of result
This is more verbose than necessary, because I repeated myself a lot, so that you could see the reasoning involved. There is a methodical way to do this, but I prefer to do it more like math, going along and discovering what I can. The methodical way usually gets me lost in a sea of variables (which is easy enough for a computer, but hard for my mortal human brain).
I hope this helped.

from types to write a function that satisfies the types

This question is taken from an exam. I don't know how to do that. :-(
Question: Give an example of a haskell or ml function whose type is
( a -> b ) -> ( c -> a ) -> c -> b
How to do that?
What meaningful function could have the type mystery :: ( a -> b ) -> ( c -> a ) -> c -> b?
Let's see, what could
mystery f g x
be?
It has three things to work with,
one value x of type c,
one function g of type c -> a and
one function f of type a -> b.
It shall produce a value of type b.
The only argument that has anything to do with b is the function f, so the result must be f ???.
What can be the argument of f here? It must have type a, and the only way to produce a value of that type from the given arguments (ignoring bottoms, undefined, error "foo") is applying g to something, so it must be
mystery f g x = f (g ??)
But what could g be applied to? That must be a value of type c. Apart from bottoms, the only value of type c that can be constructed from the arguments is x, so
mystery f g x = f (g x)
must be function composition (or undefined).
The other answers so far don't actually show the logical procedure for doing this in general. I won't show it in 100% detail either, but I'll give an example of it.
The "deep" trick to this is that finding a function of a given type is equivalent proving a a logical theorem. Using a form of Lemmon's System L (a friendlier form of natural deduction used in some beginning logic courses), your example would go like this:
Theorem: ??? :: (a -> b) -> (c -> a) -> c -> b
1. f :: a -> b (aux. assumption)
2. g :: c -> a (aux. assumption)
3. x :: c (aux. assumption)
4. g x :: a (2, 3, -> elim; assumes 2, 3)
5. f (g x) :: b (1, 4, -> elim; assumes 1, 2, 3)
6. \x -> f (g x) :: c -> b (3, 4, -> intro; discharges 3, assumes 1, 2)
7. \g x -> f (g x) :: (c -> a) -> c -> b
(2, 6, -> intro; discharges 2, assumes 1)
8. \f g x -> f (g x) :: (a -> b) -> (c -> a) -> c -> b
(1, 7, -> intro; discharges 1)
The idea here is that there is a tight correspondence between functional programming languages and logic, such that:
Types correspond to logical propositions
Function definitions correspond to logical proofs
Logical proof rules correspond to rules on how to construct programming language expressions.
So the "auxiliary assumption" logical proof rule (steps 1-3) corresponds to introducing a fresh free variable. The implication elimination rule (steps 4-5, a.k.a. "modus ponens") corresponds to function application. The implication introduction rule (steps 6-8, a.k.a. "hypothetical reasoning") corresponds to lambda abstraction. The concept of discharging auxiliary assumptions corresponds to binding free variables. The concept of a proof with no premises corresponds to the concept of an expression with no free variables.
That function is the function composition operator, and by typing the function's type into Hoogle you could find that out: http://www.haskell.org/hoogle/?hoogle=%28+a+-%3E+b+%29+-%3E+%28+c+-%3E+a+%29+-%3E+c+-%3E+b++
You can then click to show the source:
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)

Resources