I need to find a function with the signature of:
'a -> 'b -> ('a * 'b -> 'b) -> 'b
So i tried to do it like this:
fun f a b g = g(a,b)
and got the result:
val f = fn : 'a -> 'b -> ('a * 'b -> 'c) -> 'c
How can I set this c to a b as required?
Thank you very much.
You can write an explicit type annotation, for instance:
fun f a b (g : _ * 'b -> 'b) = g(a,b)
(* val f = fn : 'a -> 'b -> ('a * 'b -> 'b) -> 'b *)
The inferred type 'a -> 'b -> ('a * 'b -> 'c) -> 'c is strictly more general than the type 'a -> 'b -> ('a * 'b -> 'b) -> 'b you impose.
On type annotations for functions, see also this question.
The problem is that g(a,b) does not restrict the resulting type.
The only value of type 'b that you have access to is the second argument, so you need to return that somewhere, or use it to somehow restrict the result.
A very simple solution is to add a condition,
- fun f a b g = if false then b else g(a,b);
val f = fn : 'a -> 'b -> ('a * 'b -> 'b) -> 'b
Addendum, weeks later, as I suddenly remembered a more elegant solution, without the ugly conditional.
Since g's result should have the same type as its second argument, you can feed it its own result.
This will force b and g(a,b) to have the same type:
- fun f a b g = g(a, g(a,b));
val f = fn : 'a -> 'b -> ('a * 'b -> 'b) -> 'b
Related
I am new to SML (meta-language).
Can anyone tell me how to derive the function from the type given as below:
(’a -> ’b) -> (’b list -> ’c) -> ’a -> ’c list
I am having a hard time in understanding the curried functions in SML.
This will work
- fun f g h x = [h [g x]];
> val ('a, 'b, 'c) f = fn : ('a -> 'b) -> ('b list -> 'c) -> 'a -> 'c list
Here's how I did it.
We are given the type
('a -> 'b) -> ('b list -> 'c) -> 'a -> 'c list
So we know we want a function with three curried arguments, the first two are functions, and the third is anything. So we write:
fun f g h x = ....
Now the first argument is a function that takes in something of type 'a, which x is so we want a
g x
on the right hand side. That will be of type 'b. Now h takes in a 'b list, so we can write
h [g x]
This produces a value of type 'c, but we want f to return a 'c list so we just put that in a list, so we get:
fun f g h x = [h [g x]];
val g1 = fn x => fn y => fn z => (x y) :: z;
val g1 = fn : ('a -> 'b) -> 'a -> 'b list -> 'b list
This is the code and output. I have no idea why the output is like this.
I understand 'b list -> 'b list since z is obviously a list so (x y) :: z is list as well.
However, I do not understand why fn x => fn y is ('a -> 'b) -> 'a.
I have no idea why it is ('a -> 'b) -> 'a.
Please give me a good strategy to understand this code.
There is nothing there that has type ('a -> 'b) -> 'a.
-> associates to the right, so
('a -> 'b) -> 'a -> 'b list -> 'b list
is
('a -> 'b) -> ('a -> ('b list -> 'b list))
and so does the definition;
fn x => fn y => fn z => (x y) :: z
is
fn x => (fn y => (fn z => (x y) :: z))
That is,
x is 'a -> 'b
y is 'a
z is 'b list
the result is 'b list
Perhaps it gets clearer if you uncurry the function
fun g2(x, y, z) = (x y) :: z
which has type
(('a -> 'b) * 'a * 'b list) -> 'b list
I want to write a function that will combine all the elements in a list in OCaml. Simple enough, so far I have a working function:
let rec comAll (f : 'a -> 'a -> 'a) (r : 'a) (l : 'a list) : 'a =
match l with [] -> r
| hd::tl -> let comAll2 = comAll f r tl in f hd comAll2
;;
The First argument is a function, the second is a default value to return when/if the input list is empty, and the third argument is the list itself.
This function works as intended, except when I try to call it using another function, for example:
let inList (l : 'a list) (e : 'a) : bool = comAll (fun x y -> if x == e then true else y) false l ;;
which will pass as a function, returning inList : bool list -> bool -> bool = <fun> however, I want to instead have it return inList : 'a list -> 'a -> bool = <fun>
I have tried instead defining comAll as: let rec comAll f r l =... and that works, but I want to declare the function with explicit types.
Any help or guidance on what I am doing incorrect here?
You are declaring your parameter f to be of type 'a -> 'a -> 'a but you want to pass a function of type 'a -> bool -> bool. In other words, you want to have two different types. You should declare f to be of type 'a -> 'b -> 'b. The rest will follow.
# let rec comAll (f : 'a -> 'b -> 'b) (r : 'b) (l : 'a list) : 'b =
match l with [] -> r
| hd::tl -> let comAll2 = comAll f r tl in f hd comAll2 ;;
val comAll : ('a -> 'b -> 'b) -> 'b -> 'a list -> 'b = <fun>
# let inList (l : 'a list) (e : 'a) : bool =
comAll (fun x y -> if x == e then true else y) false l;;
val inList : 'a list -> 'a -> bool = <fun>
I'm not sure i solved this correctly.
Can you help me?
fun y z x -> x [z] y;;
This was my idea:
fun 'a -> 'b -> 'c -> ....
Now, on the right side of -> should stay the function x that takes the list [z] as parameter and then takes the y as parameter. ok?
So the type of x is : 'b list -> 'a -> 'c ok?
So it becames: 'a -> 'b -> ('b list -> 'a -> 'c) -> and then I just have to add the result of evaluation of x [z] y that is 'c and i get in the end:
'a -> 'b -> ('b list -> 'a -> 'c) -> 'c Is it correct?
Your understanding is correct, good job!
I have a foo function defined as follows
fun foo x y = x (x (x y));
How to deduce the function type?
The answer is:
val foo = fn : ('a -> 'a) -> 'a -> 'a
This process is called type inference which is done in SML by Hindley–Milner algorithm.
First let's start with a generic type signature for foo:
val foo = fn : 'c -> 'b -> 'a
where x has type 'c and y has type 'b.
We have the following steps:
x y is function application, x should have signature 'b -> 'd and we have an equation 'c = 'b -> 'd and x y has type 'd.
x (x y) means we apply a function type 'b -> 'd on an argument type 'd so 'd = 'b and 'c = 'b -> 'b.
x (x (x y)) means we apply a function type 'b -> 'b on an argument type 'b and return 'a (type of foo); it suffices 'b = 'a.
after unification, we have 'c = 'a -> 'a and 'b = 'a and foo has a generic type: val foo = fn : ('a -> 'a) -> 'a -> 'a