Lambda calculus (SML) - Apply a church number to another - sml

I'm trying to understand the exponentiation function on Church numerals:
fun power m n f = n m f;
In it, I see a multiplication. I know that it's wrong, because the multiplication is:
fun times m n f = m ( n f );
and I think to have understood it.
The problem is that I'm not able to understand what function produces the application of a church number to another.
For example, what does this expression produce?
( fn x => fn y => x ( x y ) ) ( fn x => fn y => x ( x ( x y ) ) );
Thanks

if the result of your calculation is a church number, you can calculate its int-value by passing a successor-function and zero:
(fn x=> x+1) 0
In your example:
( fn x => fn y => x ( x y ) ) ( fn x => fn y => x ( x ( x y ) ) ) (fn x=> x+1) 0;
the result is:
val it = 9 : int
so you calculated 3^2
The Term
( fn x => fn y => x ( x y ) ) ( fn x => fn y => x ( x ( x y ) ) )
reduces to
( fn x => fn y => x ( x ( x ( x ( x ( x ( x ( x ( x y ) ) ) ) ) ) ) ) )
But sml can not reduce to this term, it needs the parameters so it can calculate a concrete value.
A better language for playing with Lambda Calculus is Haskell, because it uses lazy evaluation.
You can reduce the term
( fn x => fn y => x ( x y ) ) ( fn x => fn y => x ( x ( x y ) ) )
by yourself:
fn x => fn y => x (x y) (fn x => fn y => x (x (x y) ) )
reduce x with (fn x => fn y => x (x (x y) ) ):
fn y => (fn x => fn y => x (x (x y) ) ) ( (fn x => fn y => x (x (x y) ) ) y)
rename y to a in the last (fn x => fn y => x (x (x y) ) )
and rename y to b in the first (fn x => fn y => x (x (x y) ) ):
fn y => (fn x => fn b => x (x (x b) ) ) ( (fn x => fn a => x (x (x a) ) ) y)
reduce x in (fn x => fn a => x (x (x a) ) ) with y:
fn y => (fn x => fn b => x (x (x b) ) ) ( fn a => y ( y (y a) ) )
reduce x in (fn x => fn b => x (x (x b) ) ) with ( fn a => y ( y (y a) ) ):
fn y => fn b => ( fn a => y ( y (y a) ) ) ( ( fn a => y ( y (y a) ) ) ( ( fn a => y ( y (y a) ) ) b) )
we reduce a with b in the last term:
fn y => fn b => ( fn a => y ( y (y a) ) ) ( ( fn a => y ( y (y a) ) ) ( y ( y (y b) ) ) )
we reduce a with ( y ( y (y b) ) ) in the last term:
fn y => fn b => ( fn a => y ( y (y a) ) ) ( y ( y (y ( y ( y (y b) ) ) ) ) )
we reduce a with ( y ( y (y ( y ( y (y b) ) ) ) ) ) in the last term:
fn y => fn b => y ( y (y ( y ( y (y ( y ( y (y b) ) ) ) ) ) ) )
we are done!

Related

How to pass values of variables in OCaml

In imperative languages I can easily write something like this:
if(x > y) {
int t = x;
x = y;
y = t;
}
The values of the variables are getting passed to another. However if I try writing this in Ocaml, the compiler sees this as a comparison, so it turns out to be bool:
if x > y then
let t = x in
let x = y in
let y = b in
How can I pass the value of variables to another?
Rather than variables, OCaml has named values. If you want to shuffle the names of some values, you can write:
let x, y =
if x > y then y, x
else x, y
in
If you want to mirror the imperative code exactly you would write:
# let x = ref 2;;
val x : int ref = {contents = 2}
# let y = ref 1;;
val y : int ref = {contents = 1}
# let swap_if x y = if !x > !y then let t = !x in x := !y; y := t;;
val swap_if : 'a ref -> 'a ref -> unit = <fun>
# swap_if x y;;
- : unit = ()
# !x, !y;;
- : int * int = (1, 2)
Writing it functional you would do
let (x, y) = if x > y then (y, x) else (x, y)
or
let (x, y) = (min x y, max x y)
But note that this will not change x and y. Rather it creates new variables x and y that shadow the previous bindings.

Unboxed typed int in OCaml

I would like to represent two types of integers in my OCaml program and have the compiler emit an error when one type is used in place of the other. My program converts between the two integer types, and a large fraction of the run time is spent operating on such values. If possible, I would like arithmetic operations to run on unboxed values. I implemented a module that defines such a type, and that implements the +, -, /, * operators. But my understanding is that the operations run on boxed values. Is there a way of getting the same behavior with unboxed values?
module SkipInts = struct
type t = Int of int | SkipInt of int
end
You could use private type abbreviations to create a distinct type for SkipInt represented as an int:
module SkipInt : sig
type t = private int
val of_int : int -> t
val to_int : t -> int
end = struct
type t = int
let of_int x = x
let to_int x = x
end
let _: SkipInt.t = SkipInt.of_int 42
let _: int = (SkipInt.of_int 42 :> int) (* :> can be used instead of SkipInt.to_int *)
let _: SkipInt.t = (42 :> SkipInt.t) (* Error: Type int is not a subtype of SkipInt.t *)
It sounds like you might want something like
module Make_int(): sig
type t [##immediate]
val of_int: int -> t
val to_int: t -> int
type op := t -> t -> int
val ( + ): op
val ( * ) : op
val ( - ): op
val ( / ): op
val ( ~- ): t -> t
end = struct
type t = int
let to_int x = x
let of_int x = x
let ( + ) = ( + ) let ( - ) = ( - ) let ( * ) = ( * ) let ( / ) = ( / )
let ( ~- ) = ( ~- )
end
then any call to Make_int will create a new unboxed int type incompatible with any other type
module Int_1 = Make_int()
module Int_2 = Make_int ()
let fine = Int_1.( of_int 0 + of_int 2 )
let error = Int_1.( of_int 0 + 2 )
let also_error = Int_1.(of_int 0 + Int_2.of_int 1)

Getting max value from a list in SML

I'm currently studying SML and I'm having a hard time understanding the code below
fun good_max (xs : int list) =
if null xs
then 0
else if null (tl xs)
then hd xs
else
(* for style, could also use a let-binding for (hd xs) *)
let val tl_ans = good_max(tl xs)
in
if hd xs > tl_ans
then hd xs
else tl_ans
end
hd xs is of type int and tl_ans, I think is of type list.
Why does this code work? How does the system evaluate the recursion?
It would be great if you could use xs = [3, 4, 5] to show me how this works.
Let me first rewrite this code to an equivalent but more readable version:
fun max(x,y) = if x > y then x else y
fun goodMax(nil) = 0
| goodMax(x::nil) = x
| goodMax(x::xs) = let val y = goodMax(xs) in max(x,y) end
Now we can consider how evaluation of goodMax([3,4,5]) proceeds: conceptually, it will be reduced to an answer by repeatedly substituting the respective branch of the function definition(s):
goodMax([3,4,5])
= goodMax(3::[4,5])
= let val y = goodMax([4,5]) in max(3, y) end
= let val y = goodMax(4::[5]) in max(3, y) end
= let val y = (let val y' = goodMax([5]) in max(4, y') end) in max(3, y) end
= let val y = (let val y' = goodMax(5::nil) in max(4, y') end) in max(3, y) end
= let val y = (let val y' = 5 in max(4, y') end) in max(3, y) end
= let val y = max(4, 5) in max(3, y) end
= let val y = (if 4 > 5 then 4 else 5) in max(3, y) end
= let val y = 5 in max(3, y) end
= max(3, 5)
= if 3 > 5 then 3 else 5
= 5
I have renamed the y in the inner invocation to y' for clarity.

How to do the Comparison of Two Functions

I would like to know how to compare two function F(x) & G(x) in SML, which two functions must return the same value that f(x)==g(x), where 1<= x <= 100.
For example:
- fun f x = x*x;
val f = fn : int -> int
- fun g x = x+x;
val g = fn : int -> int
- iden f g;
val it = false : bool
- fun f x = x*x;
val f = fn : int -> int
- fun g x = if x<0 then 0 else x*x;
val g = fn : int -> int
- iden f g;
val it = true : bool
Since testing whether or not two functions (programs) are equal for all inputs is not computable, your iden function will likely have to take more parameters than just the two functions that its comparing.
In general, your iden will be:
- fun iden f g elem = f(elem) = g(elem)
val iden = fn : ('a -> ''b) -> ('a -> ''b) -> 'a -> bool
In your specific case, you would probably want to do something like this:
- fun iden f g = let
= fun iden_h f g (a, b) =
= if a > b then iden_h f g (b, a)
= else if a = b then f(a) = g(a)
= else f(a) = g(a) andalso iden_h f g (a+1, b)
= in
= iden_h f g (1, 100)
= end
val iden = fn : (int -> ''a) -> (int -> ''a) -> bool
-
- iden (fn x => x + x) (fn x => 2 * x);
val it = true : bool
- iden (fn x => x + x) (fn x => x * x);
val it = false : bool

ML - datatype and functions

We have the next dayatype:
datatype complex = Rec of real * real | Polar of real * real;
and two functions:
- val real =
fn (Rec(x,y) ) => x
| (Polar(r,a)) => r * Math.cos(a);
val real = fn : complex -> real
- val imaginary =
fn (Rec(x,y) ) => y
| (Polar(r,a)) => r * Math.sin(a);
val imaginary = fn : complex -> real
Now, the book defined another function:
- val add_complex =
fn (Rec(x, y), Rec(x', y')) => ( Rec( x + x', y + y') )
| (Rec(x,y), z) => ( Rec( x + real(z), y + imaginary(z) ) )
| (z, Rec(x, y)) => ( Rec( real(z) + x, imaginary(z) + y) )
| (z,z') => (Rec( real(z) + real(z'), imaginary(z) + imaginary(z') ) );
val add_complex = fn : complex * complex -> complex
I didn't understand what is the z in the function add_complex.
Is it the Polar (meaning, I can write Z=polar(a,b)? If it is, so how the complier know it? meaning - Is it get a z, and parse it to polar variable?
If it is not polar, So what it can be?
In your code, both z and z' are Polar because the first case covers all of the possibilities in which both are Rec, so in the second case z is not Rec, or it would have used the first case. Similarly in the other cases, each z and z' must be Polar because otherwise it would have been caught by a previous case instead. Thus you can safely write z=Polar(a,b), or more accurately z=Polar(r, a) for radius and angle.