Declare multiple variable bindings in one line in SML - functional-programming

Is it possible to declare multiple variable bindings in one line in SML? For example, I have the following:
let
val m1 = [1]
val m2 = [2]
val m3 = [3]
in
{...}
end
I would like to condense this down to something like
let
val m1 = [1], m2 = [2], m3 = [3]
in
{...}
end
This syntax doesn't work, but is there a way to declare multiple variable bindings in one line like this?

Here are two ways:
- let val x = 1 val y = 5 in x + y end;
val it = 6 : int
- let val x = 1 and y = 5 in x + y end;
val it = 6 : int
I personally find the slight abuse of and more readable.
However, I think the "destructuring bind" method is more common than either of these, since it's also more generally useful.
- let val (x, y) = (1,5) in x + y end;
val it = 6 : int
- fun f x = (x, x + 2, x + 3);
val f = fn : int -> int * int * int
- let val (x, y, z) = f 3 in x + z end;
val it = 9 : int

You could create a tuple and immediately destructure it.
let
val (m1, m2, m3) = ([1], [2], [3])
in
...
end

Related

infinitely recursive type in OCaml

I'm reading this OCaml file and it contains the following:
type z = Z of z
This looks like z is infinitely recursive. How is it useful and how can I even construct such a type?
I don't think this type is particularly useful, except possibly as a test case in type theory.
You can construct values of the type like this:
# let rec x = Z x;;
val x : z = Z <cycle>
# let rec q = Z (Z q);;
val q : z = Z (Z <cycle>)
Once you have a value of the type you can readily construct other values of course:
# let y = Z (Z x);;
val y : z = Z (Z (Z <cycle>))

Value Bindings in SML? [duplicate]

This question already has answers here:
Value of bindings in SML?
(2 answers)
Closed 6 years ago.
Could someone please help. I don't get the sequence of evaluation here and how we got values of "ans". e.g. in the first example there's no value of y and I'm not sure whether this returns a pair or calls x ! (fn y => y x). It would be very helpful if you can Trace each expression.
val x = 1
val f = (fn y => y x)
val x = 7
val g = (fn y => x - y)
val ans = f g
val ans = 6 : int
=====================================
fun f p =
let
val x = 3
val y = 4
val (z,w) = p
in
(z (w y)) + x
end
val x = 1
val y = 2
val ans = f((fn z => x + z), (fn x => x + x + 0))
val ans = 12 : int
There are a few things which help make problems like this much clearer
when trying understand an alien function Lexical scoping works.
add in types to the parameters and return values without modifying the program, the compiler will tell you if you get it wrong...
replace anonymous functions with named ones.
rename variable bindings that have the same names but refer to different lexical scope.
remove variable bindings that only get used once.
binding a value to a name does not actually perform any computation,
so is merely for the benefit of the reader, if it is not doing that job
it merely serves to obfuscate, then by all means remove it.
fun f (y1 : int -> 'a) = y1 1 : 'a;
fun g (y2 : int) = 7 - y2 : int;
val ans : int = f g;
so g is given as a parameter to f, f calls g giving it the parameter x having the value 1 making y2 = 1, which g subtracts 7 - 1 returning 6.
the return value of g is an int, thus f's 'a type when g is applied to it is an int.
for the 2nd one clean it up a bit, I pulled the anonymous fn's out into their own and named values and call f (foo, bar) to make it more readable...
fun f p =
let val x = 3
val y = 4
val (z, w) = p
in (z (w y)) + x end
fun foo z = z + 1;
fun bar x = x * 2;
val ans = f(foo, bar);
Finally, we can get rid of the let values which are only used once
and replace the (z,w) = p with just (z, w) as a parameter to the function which should be much easier to follow
fun f (z, w) = (z (w 4)) + 3
fun foo z = z + 1;
fun bar x = x * 2;
val ans = f(foo, bar);
val ans = ((4 * 2) + 1) + 3

OCaml Redefining Infix Operator

An exercise questions asks for an explanation as to why this won't work. Obviously from running the code I see that it doesn't, but I don't see in this case why. The error doesn't clarify much!
# let (+) x y z = x + y + z in 5 + 6 7;;
Error: This expression has type int
This is not a function; it cannot be applied.
Thanks!
Lets go step-by-step. Fire a REPL and type:
# let (+) x y z = x + y + z;;
val ( + ) : int -> int -> int -> int = <fun>
We can interpret this int -> int -> int -> int as an infix + operator that takes two ints and returns an int -> int function.
Lets check that:
# let f = 5+6;;
val f : int -> int = <fun>
# f 7;;
- : int = 18
That's every step of your intended program working.
The issue with your code is that this doesn't work:
# 5+6 7;;
Error: This expression has type int
This is not a function; it cannot be applied.
That happens because function application has a precedence over + operator. (In fact, function application has the strongest precedence in OCaml.) So adding the brackets, fixes it (you'll need to restart the toplevel):
# let (+) x y z = x + y + z in (5+6) 7;;
- : int = 18

Standard ML: Confusion about Reference Cells

I'm reading Harper's Intro to SML and am a bit confused on reference cells. On p. 114, he gives the following example:
val r = ref 0
val s = ref 0
val _ = r := 3
val x = !s + !r
val t = r
val _ = t := 5
val y = !s + !r
val z = !t !r
"After execution of these bindings, x is bound to 3, y is bound to 5, and z is bound to 10."
Here's my trace of his code:
val r = ref 0 //allocates storage for r and sets to 0
val s = ref 0 //allocates storage for s and sets to 0
val _ = r := 3 //sets r = 3
val x = !s + !r //sets x = 0 + 3 = 3
val t = r //sets t = 3
val _ = t := 5 //sets t = 5
val y = !s + !r //sets y = 0 + 3 = 3
val z = !t !r //sets z = 5 + 3 = 8
My x is correct (3), but my y and z are both wrong (my y is 3 instead of 5 and my z is 5 instead of 10).
Where am I going wrong here?
Also, why is val _ = t := 5 necessary instead of simply t := 5?
Thanks,
bclayman
val t = r does not set t to 3. It sets t to be the same reference cell that r is.
Thus, when you do t := 5, you set both the contents of t and r to 5, since both contain the same reference cell.
As for your other question, t := 5 is a function call of the function := : 'a ref * 'a -> unit. Thus, t := 5 is an expression that evaluates to ().
val _ = t := 5 simply throws away the () and turns it into a declaration rather than an expression.
val t = r makes t an alias for r. They both refer to the same location in the store. Thus t := 5 has the side effect of changing the contents of the memory location that r refers to as well (since t and r refer to the same place). Hence
val y = !s + !t
sets y = 0 + 5 = 5.
You are correct that val _ = t := 5 is basically the same as t := 5, though the former suppresses output in the REPL (by discarding the value of the assignment expression).

Is this OCaml function composition operator definition/expression correct?

let (++) f g x = f (g x) in
let f x = x + 1 in
let g x = x * 2 in
(f++g) 1;;
Is the above expression correct?
It seems to me that the above code should be just like defining f++g x = 2 * x + 1. Am I correct?
Your implementation of function composition is correct, since :
(g ∘ f)(x) = g(f(x)) for all x in X
according to wikipedia
I get :
- : int = 3
in ocamlktop

Resources