SML: Interpret function from its type - sml

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]];

Related

Writing the Z combinator in Ocaml

I'm new to lambda calculus, and I find the grammar sometimes ambiguous to me.
Specifically, I'd like to know how to understand the Z combinator:
Z = λ f. (λ x. f (λ v. xxv)) (λ x. f (λ v. xxv))
How to write it in OCaml?
Updated:
I get error when writing like this:
fun f-> let g = fun x -> f(fun v-> x x v)in g g;;
Error: This expression has type 'a -> 'b -> 'c
but an expression was expected of type 'a
The type variable 'a occurs inside 'a -> 'b -> 'c
Typing the Z-combinator requires either to allow recursive types (with the -rectypes option) or to box the type recursion inside a type constructor:
type 'a fix = Fix of ('a fix -> 'a)
let z f =
(fun (Fix x as fx) -> f (fun v -> x fx v))
(Fix (fun (Fix x as fx) -> f (fun v -> x fx v)))
Essentially, we are replacing
x x v
which requires x to accept itself as an argument which leads to the recursive type 'a -> 'b -> 'c as 'a by
x fx v
which boxes the recursive type as ('a -> 'b) fix -> 'a -> 'b

ML programming language - Curry Function

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

OCaml type error for lists

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>

OCaml type-inference of fun y z x -> x [z] y;;

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!

Type of a function in SML

Can anyone explain to me why the type of the function given below is
('a * 'b -> 'b) -> 'b -> 'a list -> 'b?
The function is:
fun foldr f b [] = b
| foldr f b (x::xs) = f (x, (foldr f b xs))
When I look at this function, I find the type should just be ('a * 'b -> 'b) -> 'b since we have a function f which is taking in a tuple and just returning at 'b and also in the base case we return the 'b.
To determine the type of a function, the process basically goes like this:
Given a function,
fun foldr f b [] = b
| foldr f b (x::xs) = f (x, (foldr f b xs))
assume all types of the parameters and return value are unknown.
foldr : 'a -> 'b -> 'c -> 'd
f (arg1): 'a
b (arg2): 'b
(arg3): 'c
(return): 'd
fun foldr f b [] = b
First of all, we can see that b (arg2) is the same as the return type of foldr (return) and (arg3) is a list of some unknown type.
f (arg1): 'a
b (arg2): 'b
(arg3): 'e list
(return): 'b
| foldr f b (x::xs)
x and xs make up the list of (arg3).
f (arg1): 'a
b (arg2): 'b
(arg3): 'e list
(return): 'b
x : 'e
xs : 'e list
= f (x, (foldr f b xs))
Then f (arg1) is a function that takes a 2-tuple and returns the same type as foldr returns (return). The first item of the tuple is the same type of x. The second item of the tuple is the same type of the return type of foldr (return). The types also hold so far for the recursive call to foldr.
f (arg1): 'e * 'b -> 'b
b (arg2): 'b
(arg3): 'e list
(return): 'b
x : 'e
xs : 'e list
fun foldr f b [] = b
| foldr f b (x::xs) = f (x, (foldr f b xs))
It cannot be simplified any further so we have the type:
foldr: ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
I think that the above code for foldr is incorrect; it should be
fun foldr f b [] = b
| foldr f b (x::xs) = (f x (foldr f b xs))
That is, it should not be passing in a tuple of arguments, but rather passing in the accumulator and the recursive call to foldr as arguments as usual.
As for where the type comes from, remember that foldr takes in three parameters:
The function to apply over the range.
The initial value of the accumulator.
The range over which to fold.
Let's say that the accumulator has type 'b and that the list has type 'blist. We know that the overall return type of the function should be 'b, because we have
fun foldr f b [] = b
Let's now see what the type of f is. We have this:
foldr f b (x::xs) = (f x (foldr f b xs))
This takes in the first element of the list and the accumulator, then produces something that must be of type 'b. The list has type 'a list and the accumulator has type 'b, so the function has type ('a * 'b -> 'b).
Summing this up, the type of the function is
('a * 'b -> 'b) -> 'b -> 'a list -> 'b
Which is what is being reported.