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";
Related
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.
I'm actually not sure this is doable with monads or that it should be done with them and I'm looking for a solution rather than solve it with monads if monads are not the solution.
Let's say I have the following code (simplified but the idea is here):
module IM = Map.Make (Int)
let f k v m =
if IM.mem k m then (m, true)
else (IM.add k v m, false)
let a =
let m = IM.empty in
let m, res = f 0 "Zero" m in
if res then
let m, res = f 1 "One" m in
if res then f 2 "Two" m else (m, res)
else (m, res)
I'm repeating multiple times:
let value, boolean = function application to value and other values in
if boolean then another function application to the new value and other values (not the same as the first one)
else the result
This means that these functions don't necessarily have the same type but they all return a a IM.t * bool (a being the same type for every function)
I wondered if it was possible to create an inline operator that would allow me to do it.
I tried something like:
module EqMonad = struct
let ( let* ) (t, res) f2 = if res then f2 t else (t, false)
let return t = t
end
But it'll obviously not work because f2 takes more than one argument but needs to receive t as its last argument.
I guess I could summarize my problem like this:
Is it possible to have monads wrapping variadic functions?
Your solution works (with return corrected to be the monadic return) and is a restricted version of the error monad:
let return x = x, true
let a =
let m = IM.empty in
let* m = f 0 "Zero" m in
let* m = f 1 "One" m in
let* m = f 2 "Two" m in
return m
However, since the control flow never depends on the value of m, this is a sign that it might simpler to use a regular function:
let rec add_first_fresh m l = match l with
| [] -> None
| (k,v):: q ->
if IM.mem k m then add_first_fresh m q
else Some (IM.add k v m)
let a = add_first_fresh IM.empty
[0, "Zero";
1, "One";
2, "Two"
]
Im trying to write a function that does the following, takes in :
[ #"t" ,#"h" ,#"e" ,#" " ,#"c" ,#"a" ,#"t" ]
The following is the output:
( [#"t" ,#"h" ,#"e" ] , [#" " ,#"c" ,#"a" ,#"t" ] )
so far I have..
fun isLetter c = #"a" <= c andalso c <= #"z";
//(this works fine and is used within the main function wordPop)
fun wordPop [] = ([],[])
| wordPop (hd::tl) = if not (isLetter hd)
then ([], hd::tl)
else (* ...not too sure... (1) *)
I know that I have to do something that looks like this at (1)
let (wordPop tl) in (x,y) end;
and somehow add hd to x. But not 100% sure how to do this.
Sounds like homework, so here is a hint:
In the non-basis case (hd::tl), if isLetter hd is false then you are ready to directly return something (no need for a recursive function call). Think carefully about what you want to return if the input looks like just explode(" cat") (i.e. [#" ", "c", "a", "t"] -- note the space).
As far as the other case (isLetter hd evaluating to true) goes, suppose you are processing the characters in "he cat". Then hd = #"h" and tl = [#"e", #" ", "c", "a", "t"].
If in this context you execute
let val (x,y) = wordPop tl
then x = [#"e"] and y = [#" ", "c", "a", "t"].
Given such x and y -- where do you want to place hd = #"h" before returning?
The final solution I got:
fun isLetter c = #"a" <= c andalso c <= #"z";
fun wordPop [] = ([],[]) |
wordPop (hd::tl) = if(not (isLetter hd))
then ([],(hd::tl))
else let val (x,y) = wordPop tl in (hd::x,y) end;
I'm writing a function in sml using emacs and when I try to compile this code
fun tryDivide small n =
if n = 1 then true
else if ((small mod n) = 0) then tryDivide small (n-1)
else false
fun lcmHelper small div =
if tryDivide (small div) = false then lcmHelper ((small+div) div)
else small
(*Start by calling this*)
fun lcm d =
val small = d
lcmHelper (small d)
It is supposed to find the lowest value that can be divided by d (fun lcm d)
I am pretty sure that the algorithm works, but there are syntax errors.
At the start of the "fun lcm d =" I get an error that says "Error Inserting EQUALOP"
Any ideas what might be causing this?
Thanks in advance!
fun lcm d =
let
val small = d
in
lcmHelper (small d)
end
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...
val record1 = {hour = 11, min = 45, f = "PM"};
val record2 = {hour = 2,min = 13,f = "AM"};
fun timerrecord(record1,record2)=
if (#f record1 = "PM") andalso (#f record2="AM") then "t1 comes First"
else if(#f record1 = "AM") andalso (#f record1="PM") then "t2 comes First"
else if (#hour record1 > #hour record1) then "t1 comes First"
else if (#hour record1 < #hour record1) then "t2 comes First"
else if (#min record1 > #min record1) then "t1 comes First"
else "t2 comes First";
The problem is when I write it without the function, it gives the correct result but when I put code in that function (as given above) it gives an error...UNRESOLVED FLEX RECORD.
t1,t2 and record1,record2 are timestamps.
I am new to SML, so any help would be helpful. Thanks in advance.
As user987339 said, you can put in type annotations to resolve the types. But the common way to do this in ML is not to use record selectors #label in the first place, but to rely on pattern matching, which implies the types:
fun timerRecord({hour = h1, min = m1, f = f1}, {hour = h2, min = m2, f = f2}) =
if f1 = "PM" andalso f2 = "AM" then "t1 comes first"
else if f1 = "AM" andalso f2 = "PM" then "t2 comes first"
else if h1 > h2 then "t2 comes first"
else if h1 < h2 then "t1 comes first"
else if m1 > m2 then "t2 comes first"
else "t1 comes first"
(Fixed a couple of cases.)
You have to define record type in order to compile this function. So add:
type recc = {hour:int, min:int, f:string};
and change your function signature to:
fun timerrecord(record1:recc,record2:recc)=
Or you can do it a bit "dirty", just by changing function signature to:
fun timerrecord(record1:{hour:int, min:int, f:string},record2:{hour:int, min:int, f:string})=
Depends how DRY you are :-)
PS: Find what DRY means.