Writing the Z combinator in Ocaml - 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

Related

SML: Interpret function from its type

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

What is a good stategy to understand function return function in ML?

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

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.