OCaml function comparing numbers - ocaml

I am trying to write a function that takes 3 numbers, x y z. If x is equal to y, then it should return z. Otherwise, return x. I am having trouble figuring out why my attempt always returns z, even if x!=y. Any help would be appreciated I am still new to OCaml.
let test x y z =
match x with
| y when x = y -> z
| _ -> x

Your code doesn't compare x to y, it uses the pattern y to match against x. This always succeeds and binds y to the value of x. That is, you're creating a new local variable y that has the same value as x.
To fix your code, you could do this:
let test x y z =
match x with
| _ when x = y -> z
| _ -> x
But that seems a bit silly when you could just do:
let test x y z =
if x = y then z else x

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.

recursion not working as desired

the keword rec do not do anything and do not cause any segmentation fault
like this example
let rec x x=x+x in x 2;;
:-int=2
In this definition:
let rec x x = x + x
The "recursive" function name x is hidden by the parameter named x. It's just as if you had:
let rec x y = let x = y in x + x
In essence there is an inner binding that hides the recursive one.

How do you use pattern matching with lists of tuples in Haskell?

I've been trying to write a function that takes a list of tuples (in my case, three Int values within the tuple) and returns the maximum sum of any of the tuples in the list.
This is my current attempt at doing so:
type Triples = [(Int, Int, Int)]
maxTotal :: Triples -> Int
maxTotal [] = error "ERROR: NO TUPLES"
maxTotal ((x,y,z):rest)
| sumTriple x y z > maxTotal rest = sumTriple x y z
| otherwise = maxTotal rest
sumTriple :: Int -> Int -> Int -> Int
sumTriple x y z = x + y + z
However, every time I run this function, I end up with my error output... Is Haskell treating my input list of tuples as an empty list or am I cycling through to the end of the list in my "otherwise" guard then reaching the error?
Turns out my definitions for maxTotal were incomplete. All I had to add was this:
maxTotal [(x,y,z)] = x + y + z
Case closed.

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

Can an infix function have more than 2 parameters?

I am a bit confused by infix function.
So if I define let (++) x y = ..., then ++ is an infix function. I can use it as follows:
x ++ y
(++) x y
Basically if I remove parentheses, I can put 1st parameter to its left, and 2nd to its right.
Then can I define 3 parameters, like let (++) x y z = ...?
If I do let (++) x y z = x + y + z in utop, it is ok and give me:
utop # let (++) x y z = x + y + z;;
val ( ++ ) : int -> int -> int -> int = <fun>
I can use (++) 1 2 3 and answer is 6.
But is (++) an infix function? If I want to purely use ++, how should I put x,y,z around it?
# (1 ++ 2) 3;;
- : int = 6
Although I'm not sure when you would actually want to do that...