SML if and else if // boolean fuction - if-statement

I am solving this exercise that takes 2 tupples in SML (intintint) (date month and year)
"Write a function is_older that takes two dates and evaluates to true if the first argument is a
date that comes before the second argument. (If the two dates are the same, the result is false.) "
this is what i wrote :
fun is_older (x int*int*int_,y int*int*int_) =
let val r1 = #1 x
val r2 = #2 x
val r3 = #3 x
val t1 = #1 y
val t2 = #2 y
val t3 = #3 y
if r3 < t3 return true
else if r2 < t2 && r3 == t3 return true
else if r1 < t1 && r2 == t2 && r3 == t3 return true
else return false
there is an error in line 10 where we have the "else if r2 < t2 && r3 == t3 return true " . I am new to sml and i dont really know how to solve this issue .
and also can we return a boolean in SMl and how do we pass on values to it (like do we have a main fuction like in java )
i googled the issue and didnt really get an answer pls help me
type here

You have several issues with your syntax. I'm going to guess you meant:
fun is_older (x : int*int*int, y : int*int*int) =
let
val r1 = #1 x
val r2 = #2 x
val r3 = #3 x
val t1 = #1 y
val t2 = #2 y
val t3 = #3 y
in
r3 < t3 orelse
(r2 < t2 andalso r3 = t3) orelse
(r1 < t1 andalso r2 = t2 andalso r3 = t3)
end
But pattern-matching can make that:
fun is_older ((r1, r2, r3), (t1, t2, t3)) =
r3 < t3 orelse
(r2 < t2 andalso r3 = t3) orelse
(r1 < t1 andalso r2 = t2 andalso r3 = t3)
|| is replaced with orelse. && with andalso. The = operator is used for equality checks in SML, rather than ==. There is no need for a return as a function returns the last expression in it. The types are correctly inferred without having to be explicitly annotated.
Let bindings follow the form let ... in ... end.
Pattern-matching removes the need for that construct entirely.

Related

Evaluation order of let-in expressions with tuples

My old notes on ML say that
let (๐‘ฃโ‚, โ€ฆ , ๐‘ฃโ‚™) = (๐‘กโ‚, โ€ฆ , ๐‘กโ‚™) in ๐‘กโ€ฒ
is a syntactic sugar for
(ฮป ๐‘ฃโ‚™. โ€ฆ (ฮป ๐‘ฃโ‚. ๐‘กโ€ฒ)๐‘กโ‚ โ€ฆ )๐‘กโ‚™
and that
let (๐‘ฃโ‚, ๐‘ฃโ‚‚) = ๐‘ก ๐‘กโ€ฒ in ๐‘กโ€ณ
is equivalent to
let ๐‘ฃ = ๐‘ก ๐‘กโ€ฒ in
let ๐‘ฃโ‚‚ = snd ๐‘ฃ in
let ๐‘ฃโ‚ = fst ๐‘ฃ in
๐‘กโ€ณ
where
each ๐‘ฃ (with or without a subscript) stands for a variable,
each ๐‘ก (with or without a sub- or a superscript) stands for a term, and
fst and snd deliver the first and second component of a pair, respectively.
I'm wondering whether I got the evaluation order right because I didn't note the original reference. Could anyone ((confirm or reject) and (supply a reference))?
It shouldn't matter whether it's:
let ๐‘ฃ = ๐‘ก ๐‘กโ€ฒ in
let ๐‘ฃโ‚‚ = snd ๐‘ฃ in
let ๐‘ฃโ‚ = fst ๐‘ฃ in
๐‘กโ€ณ
Or:
let ๐‘ฃ = ๐‘ก ๐‘กโ€ฒ in
let ๐‘ฃโ‚ = fst ๐‘ฃ in
let ๐‘ฃโ‚‚ = snd ๐‘ฃ in
๐‘กโ€ณ
Since neither fst nor snd have any side-effects. Side-effects may exist in the evaluation of ๐‘ก ๐‘กโ€ฒ but that's done before the let binding takes place.
Additionally, as in:
let (๐‘ฃโ‚, ๐‘ฃโ‚‚) = ๐‘ก ๐‘กโ€ฒ in ๐‘กโ€ณ
Neither ๐‘ฃโ‚ nor ๐‘ฃโ‚‚ is reliant on the value bound to the other to determine its value, so the order in which they're bound is again seemingly irrelevant.
All of that said, there may be an authoritative answer from those with deeper knowledge of the SML standard or the inner workings of OCaml's implementation. I simply am uncertain of how knowing it will provide any practical benefit.
Practical test
As a practical test, running some code where we bind a tuple of multiple expressions with side-effects to observe order of evaluation. In OCaml (5.0.0) the order of evaluation is observed to be right-to-left. We observe tthe same when it comes to evaluating the contents of a list where those expressions have side-effects as well.
# let f () = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let (a, b, c) = (f (), g (), h ()) in a + b + c;;
h
g
f
- : int = 6
# let f () = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let (c, b, a) = (h (), g(), f ()) in a + b + c;;
f
g
h
- : int = 6
# let f _ = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let a () = print_endline "a" in
let b () = print_endline "b" in
let (c, d, e) = (f [a (); b ()], g (), h ()) in
c + d + e;;
h
g
b
a
f
- : int = 6
In SML (SML/NJ v110.99.3) we observe the opposite: left-to-right evaluation of expressions.
- let
= fun f() = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= val (a, b, c) = (f(), g(), h())
= in
= a + b + c
= end;
f
g
h
val it = 6 : int
- let
= fun f() = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= val (c, b, a) = (h(), g(), f())
= in
= a + b + c
= end;
h
g
f
val it = 6 : int
- let
= fun f _ = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= fun a() = print "a\n"
= fun b() = print "b\n"
= val (c, d, e) = (f [a(), b()], g(), h())
= in
= c + d + e
= end;
a
b
f
g
h
val it = 6 : int
Be aware that, in OCaml, due to the (relaxation of the) value restriction, let a = b in c is not equivalent to (fun a -> c)b. A counterexample is
# let id = fun x -> x in id 5, id 'a';;
- : int * char = (5, 'a')
# (fun id -> id 5, id 'a')(fun x -> x)
Error: This expression has type char but an expression was expected of type int
#
This means that they are semantically not the same construction (the let ... = ... in ... is strictly more general that the other).
This happens because, in general, the type system of OCaml doesn't allow types of the form (โˆ€ฮฑ.ฮฑโ†’ฮฑ) โ†’ int * char (because allowing them would make typing undecidable, which is not very practical), which would be the type of fun id -> id 5, id 'a'. Instead, it resorts to having the less general type โˆ€ฮฑ.(ฮฑโ†’ฮฑ) โ†’ ฮฑ * ฮฑ, which doesn't make it typecheck, because you can't unify both ฮฑ with char and with int.

SML: why the return type is unit?

So I have wrote a function (I will describe it briefly to avoid confusion)
fun function1 (l, a1,a2, suma, b2, sumb, d) =
while(a1<a2 andalso k>d) do
let
val k = Real.fromInt(a2-a1)
val suma = suma - Real.fromInt(List.nth(l, a1))
val sumb = sumb - Real.fromInt(List.nth(l, b2))
val a1 = a1+1
val b2 = b2-1
in
if suma<0.0 andalso ( (~sumf)/(N*k) )>1.0 andalso k>d
then k
else if sumb<0.0 andalso ((~sumb)/(N*k))>1.0 andalso k>d
then k
else d
end;
The system says this:
val function1 = fn : int list * int * int * real * int * real * real -> unit
I don't get the return type. I want to return a real like d & k . Why it's unit??

Scala: Get largest number from List of tuples

If I had a list of (String,Double) tuples in Scala
(i.e. List[(String,Double)])
, how would I get the tuple with the largest Double value?
Just use maxBy:
val list: List[(String, Double)] = List(("a", 2.3), ("b", 3.5), ("c", 8.9))
list.maxBy(_._2)
There are a few ways to do it. The one that comes to mind is by doing a .sortBy(- _._2)
val t1 = ("string1", 1)
val t2 = ("string2", 5)
val t3 = ("string3", 12)
val t4 = ("string4", 3)
val t5 = ("string5", 8)
val myList = List(t1, t2, t3, t4, t5)
val largestTuple = myList.sortBy(- _._2).head
largestTuple: (String, Int) = (string3,12)
Also reduce can convey the semantics like this,
xs.reduce( (a,v) => if (v._2 > a._2) v else a)
Namely, scan the list and preserve the max value. Even so, maxBy is the way to go for simplicity.

SML program and tuple

I am doing an exercise in which two time stamps are given and I have to find which is large. This program is written in SML.So I come up with this program....
type triple = {int,int,string};
val record1 = (11,45,"PM");
val record2 = (2,13,"AM");
fun timerrecord(record1:triple,record2:triple)=
let val (hour1:int,min1:int,f1:string) = record1;
val (hour2:int,min2:int,f2:string) = record2
in
if (f1= "AM") andalso (f2="PM") then "t1 comes First"
else if(f1 = "PM") andalso (f2="AM") then "t2 comes First"
else if (hour1 < hour2) then "t1 comes First"
else if (hour1 > hour2) then "t2 comes First"
else if (min1 < min2) then "t1 comes First"
else "t2 comes First";
above program is not executing as a whole but individual logic is because of tuple.I am not able to get best use of tuple to comparing 2 time stamps.
Also I want to know how to acess tuple as if it is known then we can easily solve this problem.
Thanks in advance.
I guess you meant
type triple = (int*int*string)
Also, you should avoid the ;, they are only necessary in the REPL. And you forgot to add end at the end of the let..in..end expression in the body of your function. Also avoid the ; or it won't compile (at least not in my version of SML).
You question is not entirely clear, and I am pretty sure there are many ways to do this. Alternatively you could try somewhat like:
fun timerrecord(record1:triple,record2:triple)=
case (record1, record2) of
((_,_,"AM"),(_,_,"PM")) => record1
| ((_,_,"PM"),(_,_,"AM")) => record2
| ((h1,m1,_),(h2,m2,_)) => if h1 < h2 then record1
else if h2 < h1 then record2
else if m1 < m2 then record1
else record2
There are few ways to do this. You can define record type in order to compile this function:
type recc = {hour:int, min:int, f:string};
and change your function signature to:
fun timerrecord(record1:recc,record2:recc)=
Or you can just by change function signature to:
fun timerrecord(record1:{hour:int, min:int, f:string},record2:{hour:int, min:int, f:string})=
ML is doing this by pattern matching:
fun timerRecord({hour = h1, min = m1, f = f1}, {hour = h2, min = m2, f = f2}) =
And your function will be :
fun timerRecord({hour = h1, min = m1, f = f1}, {hour = h2, min = m2, f = f2}) =
if (f1= "AM") andalso (f2="PM") then "t1 comes First"
else if(f1 = "PM") andalso (f2="AM") then "t2 comes First"
else if (h1 < h2) then "t1 comes First"
else if (h1 > h2) then "t2 comes First"
else if (m1 < m2) then "t1 comes First"
else "t2 comes First";

number_in_month exercise (SML error unbound variable)

I am trying to learn SML, and I am trying to implement two functions. The first function works fine, but when I added the second function it gives me an run-time error:
stdIn:1.2-1.17 Error: unbound variable or constructor: number_in_month
This happens while calling the function number_in_month. My code is:
fun is_older(d1 :int*int*int,d2 :int*int*int) =
(#1 d1) < (#1 d2) andalso (#2 d1) < (#2 d2) andalso (#3 d1) < (#3 d2)
fun number_in_month(da :(int * int * int) list ,mo : int) =
if da = []
then 0
else if (#2(hd da)) = mo
then 1 + number_in_month((tl da),mo)
else 0 + number_in_month((tl da),mo)
Your question sounds surprisingly much like these other questions: SML list iteration (8 months ago), recursion in SML (9 months ago), and Count elements in a list (8 months ago), so you certainly don't get points for asking a creative question.
Some of the questions above have been answered extensively. Look at them.
Here is your code rewritten in a better style:
(* Find better variable names than x, y and z. *)
fun is_older ((x1,y1,z1), (x2,y2,z2)) =
x1 < x2 andalso y1 < y2 andalso z1 < z2
fun number_in_month ([], mo) = 0
| number_in_month ((x,y,z)::rest, mo) =
if y = mo then 1 + number_in_month(rest, mo)
else 0 + number_in_month(rest, mo)