ML - datatype and functions - sml

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.

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.

Converting int to real in SML

Newbie at SML
I have the following code that returns the absolute value of a list. I need it to be of type int list -> real list. Where do I place the statement that converts it to real while constraining this code to a single line?
val myabs = map(fn x => if x >= 0 then x else ~x) [1,~2, 3, ~4];
You convert an int to real using Real.fromInt:
- Real.fromInt 42;
> val it = 42.0 : real
You can convert an int list into a real list by List.map Real.fromInt:
- List.map Real.fromInt [1, 2, 3];
> val it = [1.0, 2.0, 3.0] : real list
You can convert an integer to its absolute using Int.abs:
- Int.abs ~42;
> val it = 42 : int
You can combine those two functions and so both convert an integer to its absolute and convert it to real:
- (Real.fromInt o Int.abs) ~42;
> val it = 42.0 : real
And you can do this for an entire list using List.map (Real.fromInt o Int.abs):
- List.map (Real.fromInt o Int.abs) [~1, ~2, ~3];
> val it = [1.0, 2.0, 3.0] : real list
You can express that as a single function:
fun myabs xs = List.map (fn x => Real.fromInt (Int.abs x)) xs
And you can shorten this function a bit:
val myabs = List.map (fn x => Real.fromInt (Int.abs x))
val myabs = List.map (fn x => (Real.fromInt o Int.abs) x)
val myabs = List.map (Real.fromInt o Int.abs)
So the only missing pieces were:
Instead of if x >= 0 then x else ~x, use Int.abs x.
To convert x to real, use Real.fromInt x.
To apply multiple functions in sequence, f (g x) or (f o g) x, like math.

How can I divide two numbers in ML defined as a datatype?

I'm trying to write a recursive function in SML that receives two natural numbers n1,n2 and returns the result of n1 div n2
The datatype natural is defined as follows:
datatype natural = zero | Succ of natural
I want to write it in terms of the new datatype , or in other words, not by converting them to their regular form and converting back the result.
Any ideas how division is done in this definition?
You could start by defining subtraction:
exception Negative
fun sub (a, zero) = a
| sub (zero, b) = raise Negative
| sub (Succ a, Succ b) = sub (a, b)
From here, it should be pretty easy to simply count how many times you can subtract n2 from n1 without going negative. In particular, this equation should help:
n1 div n2 = 1 + (n1 - n2) div n2
I'll leave the rest to you.
Similar to Sam Westrick's definition, "number of times you can subtract n2 from n1 without going negative", you could also do integer division with addition and greater-than using the definition, "number of times you can add n2 to itself before it is greater than n1."
datatype nat = Z | S of nat
fun gt (S x, S y) = gt (x, y)
| gt (S _, Z) = true
| gt (Z, _) = false
fun add (x, Z) = x
| add (x, S y) = add (S x, y)
fun divide (_, Z) = raise Domain
| divide (x, y) = (* ... *)
Addition might seem like a conceptually simpler thing than subtraction. But greater-than is a more expensive operator than determining when a number is negative, since the case is incurred by induction, so Sam's suggestion would be more efficient.
You might test your solution with the following tests:
fun int2nat 0 = Z
| int2nat n = S (int2nat (n-1))
fun nat2int Z = 0
| nat2int (S n) = 1 + nat2int n
fun range (x, y) f = List.tabulate (y - x + 1, fn i => f (i + x))
fun divide_test () =
let fun showFailure (x, y, expected, actual) =
Int.toString x ^ " div " ^ Int.toString y ^ " = " ^
Int.toString expected ^ ", but divide returns " ^
Int.toString actual
in List.mapPartial (Option.map showFailure) (
List.concat (
range (0, 100) (fn x =>
range (1, 100) (fn y =>
let val expected = x div y
val actual = nat2int (divide (int2nat x, int2nat y))
in if expected <> actual
then SOME (x, y, expected, actual)
else NONE
end))))
end

How to split main and the rest of your code with Ocaml?

I was wondering how could I achieve the following:
have all the "business logic" in a file
have a main.ml that uses that business logic
Business logic:
type point = {x:float; y:float;}
let pi_known = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
let percentage_error pi_estimated =
((pi_known -. pi_estimated) /. pi_known) *. 100.0
let pi_and_error pi error =
Printf.sprintf "Pi's value :: %.10f Error rate :: %.10f %.%" pi error
let point_to_string { x = x; y = y } =
Printf.sprintf "%.2f %.2f" x y
let gen_point xr yr =
{x=xr; y=yr}
let distance_between_points p q =
(p.x -. q.x) *. (p.x -. q.x) +. (p.y -. q.y) *. (p.y -. q.y)
let distance_from_origin c =
distance_between_points c (gen_point 0.0 0.0)
let count_within ~counter:n =
let rec count_within_aux ~counter:n ~within:m =
match n, m with
| 0, m -> m
| n, m ->
let cc = gen_point (Random.float 1.0) (Random.float 1.0) in
let dist = distance_from_origin cc in
match dist with
| dist when dist <= 1.0 -> count_within_aux ~counter:(n - 1) ~within:(m + 1)
| dist when dist > 1.0 -> count_within_aux ~counter:(n - 1) ~within:m
| _ -> 0 in
count_within_aux ~counter:n ~within:0
let count_within_stepping ~counter:n ~stepping:s =
let rec count_within_stepping_aux ~counter:n ~within:m ~acc:acc =
match n, m, acc with
| n, m, acc when n <= 0 -> m
| n, m, acc ->
let c = count_within s in
let pi = ((float_of_int m) /. (float_of_int acc)) *. 4.0 in
let r = percentage_error pi in
print_endline (pi_and_error pi r);
count_within_stepping_aux ~counter:(n-s) ~within:(m+c) ~acc:(acc+s) in
count_within_stepping_aux ~counter:n ~within:0 ~acc:0
pi.mli:
(*
* Point in a two-dimensional Euclidean space
*)
type point = {x:float; y:float;}
val point_to_string : point -> string
val gen_point : float -> float -> point
(*
* 'Euclidean distance or Euclidean metric is the "ordinary" straight-line distance between
* two points in Euclidean space. With this distance, Euclidean space becomes a metric space.
* The associated norm is called the Euclidean norm.
* Older literature refers to the metric as Pythagorean metric.'
* https://en.wikipedia.org/wiki/Euclidean_distance
*)
val distance_between_points : point -> point -> float
val distance_from_origin : point -> float
val count_within : counter:int -> int
val count_within_stepping : counter:int -> stepping:int -> int
val percentage_error : float -> float
val pi_and_error : float -> float -> string
main.ml:
let main () =
Random.self_init();
let num_iter = Sys.argv.(1) in
let n = int_of_string num_iter in
print_endline ("Number of iterations :: " ^ num_iter);
let pi_estimated = ((float_of_int (Pi.count_within_stepping n (n / 20))) /. (float_of_int n)) *. 4.0 in
let r = Pi.percentage_error pi_estimated in
print_endline (Pi.pi_and_error pi_estimated r)
let () =
main ()
_oasis:
Name: Pi
Version: 0.1
Synopsis: Nope
Authors:
Istvan <istvan#mail.tld>
License: MIT
Homepage: http://0.0.0.0
OASISFormat: 0.4
BuildTools: ocamlbuild
Plugins: META (0.4), DevFiles (0.4)
Executable "pi"
Path: src
MainIs: main.ml
CompiledObject: best
BuildDepends:
str,unix
Unfortunatelly when I compile this and run it it returns nothing while if I merge main.ml and pi.ml it works as expected. What am I missing?
UPDTE:
After adding the mli file to the project and changing main.ml as it was suggested by #gallais it works as expected.
It turns out that mli files are necessary for using modules. Having src/x.ml and src/x.mli is required. If these files are present X can be referenced from main.ml.

Confusing SML statement

I have this statement:
let val x =
let val x = 5
in(fn y =>(y,x+y))
end
in
let val y=3 and z=10
in x z
end
end;
The output is :
(10,15)
I've been trying to track how this answer was produced but am getting confused. Is there a better way to write this that would help me understand what variables are being used where? Thank you!
First, some alpha-conversion:
let val fnPairOfInputAndInputPlus5 =
let val five = 5
in ( fn input => ( input, five + input ) )
end
in let val ignored = 3 and input = 10
in fnPairOfInputAndInputPlus5 input
end
end;
This code is demonstrating that when you declare a function value, unbound values in the declaring scope, such as the value five, are "enclosed" by the declaration (hence the term "closures"). Thus the function always returns a pair consisting of its input and its input plus five.
You could simplify it to
let fun f y = (y,5+y)
val y=3 and z=10
in
f z
end;
Note that the two instances of y are independent. The inner occurrence of x (which I've eliminated) is independent of the outer one (now renamed f).
Can be understood using manual evaluation with detailed explanations.
Starting with your initial expression:
let val x =
let val x = 5
in (fn y => (y,x + y))
end
in
let val y = 3 and z = 10
in x z
end
end;
Line 2,3,4 is an expression whose type is a function, as you see in the in part. It does not depends on any outer context, so it may be simplified as just fn y => (y, 5 + y), substituting x to 5, according to the binding given in let.
So you now have this:
let val x = fn y => (y, 5 + y)
in
let val y = 3 and z = 10
in x z
end
end;
After substitution of x (and removal of the let which in then now not necessary any more):
let val y = 3 and z = 10
in (fn y => (y, 5 + y)) z
end;
Note the y appearing in (y, 5 + y) are bound to the function's argument, and not to 3. There is no reference to this outer y, so its biding may be removed.
Now you have:
let z = 10
in (fn y => (y, 5 + y)) z
end;
Substituting z to 10 and removing the let which is not necessary any more, you get:
(fn y => (y, 5 + y)) 10;
This is a function application. You may evaluate it, to get:
(10, 5 + 10);
Which gives the final and constant result you noticed:
(10, 15);