Error SML : Error: unbound variable or constructor: valof - sml

I am taking the Programming Languages course offered by Washington University, during one of the lectures, this code popped up worked for professor Dan, however, I am getting unbound variable or constructor:valof error. Could not figure it out.
it is smlnj, and running on emacs, if it would yield any help.
fun max1(xs: int list)=
if null xs
then NONE
else
let val tl_ans = max1(tl xs)
in if isSome tl_ans andalso valof tl_ans > hd xs
then tl_ans
else SOME (hd xs)
end
here is the error: options.sml:7.37-7.42 Error: unbound variable or constructor: valof

As quoify says, it's spelled valOf.
And as kopecs says, if you use pattern matching, it will be much shorter:
fun max1 (x::y::rest) = max1 (Int.max (x, y) :: rest)
| max1 [x] = SOME x
| max1 [] = NONE
(This version also uses the library function Int.max for added brevity.)
If this is too compact, you could also write:
fun max1 (x::y::rest) = let val z = Int.max (x, y) in max1 (z::rest) end
| max1 [x] = SOME x
| max1 [] = NONE
The version from the slides deals with an annoying situation that arises in many recursive functions that return sum types like 'a option: You may need to perform a call, do some unpacking (i.e. remove SOME), and then pack the result back (i.e. add SOME again).
But the max1 problem does not necessitate that situation.

Related

how do you do pattern matching is Standard ML?

I want to write the following procedure using pattern matching:
fun sub1 ns = if null ns then []
else (hd ns) :: (sub1 (tl ns));
Where null, hd, and tl are:
fun null [] = true
| null (_::_) = false;
fun hd (x::_) = x;
fun tl (_::xs) = xs;
So far I have tried this:
fun sub1.2 [] = []
| sub1.2 (n::ns) = n :: sub1.2 ns;
The above does not work. I get the following syntax errors:
2.1.sml:6.10 Error: syntax error: inserting ASTERISK
2.1.sml:7.10 Error: syntax error: inserting ASTERISK
2.1.sml:7.33 Error: syntax error: inserting EQUALOP
So again, how do you write sub1 using pattern matching? Thanks!
Decimal points aren't allowed in names; you'll have to remove or replace them.
Since you managed to find a solution, try and see if you can rewrite the following using pattern matching:
fun merge (xs, ys) =
if null xs orelse null ys
then []
else (hd xs, hd ys) :: merge (tl xs, tl ys)
val example = merge ([1,2,3], [4,5,6]) (* [(1,4), (2,5), (3,6)] *)
You may need more than one base case, but they'd probably look very similar.

SML: Where is the syntax error

So I recently learned sml and really confused on how to use it compared to java. So I was told me make a code that takes consecutive pairs of values, adding them and inserting the sums into a new list.
If the original list has an odd length, then the first n-1 items are pairwise added, and the n-th item is simply copied as is at the end of the new list.
So my code so far is:
fun sumpairs x =
if null x then []
else (if (tl x =[]) then x
else hd x + hd(tl x) :: sumpairs(tl (tl x));
sumpairs([1,2,3]); (I want to test it on this to get something like [3,3])
but I'm getting a syntax error. And since the sml doesn't find the error for me I'm lost on what the problem or if it even works or not. I believe that is should work.
You have an unmatched parenthesis in (if (tl x =[]).
(SML's error messages are possibly the most confusing I've encountered - I get "syntax error at EOF", which is completely useless.)
It's easier to match parentheses if you use fewer:
fun sumpairs x =
if null x then []
else if tl x = [] then x
else hd x + hd (tl x) :: sumpairs (tl (tl x))
An editor that can show which parentheses match also helps.
Most modern programmer's editors can do that, if you find the magic setting.
I would recommend that you get comfortable with pattern matching - it's usually much easier to follow the logic with patterns than with a chain of conditionals:
fun sumpairs [] = []
| sumpairs [x] = [x]
| sumpairs (x::y::xs) = x + y :: sumpairs xs

Applying Fold function in F#

let list_min_fold = List.fold (fun acc -> List.min acc ) 0 lst
printfn"Using regular List.fold function:\n The minimum is: %A\n"
(list_min_fold)
When I execute my code this error displays:
error FS0001: The type '('a -> 'b)' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface
Why? Please help :(
Are you trying to find the smallest number in a list? If so, you need to use the min function (which takes just two arguments) rather than List.min (which takes a list of arguments):
To keep the code the most similar to your example, you can write (note also that starting with 0 is not going to work, so I used System.Int32.MaxValue instead):
let lst = [4;3;1;2;5;]
let list_min_fold = List.fold (fun acc -> min acc) System.Int32.MaxValue lst
It is also worth noting that the function you pass to fold takes two arguments - the state acc and the current value:
let list_min_fold = List.fold (fun acc v -> min acc v) System.Int32.MaxValue lst
But thanks to partial function application you can omit one of them (as you did), or both of them:
let list_min_fold = List.fold min System.Int32.MaxValue lst
as always Tomas answer is spot on so I have but a small remark:
as you probably saw it makes no sense to try to find the minimum of an empty list (so the function probably should be of type 'a option and when you have an non-empty list it's very easy to use List.reduce (which is basically just a fold for binary operations and min is a great candidate for such an operation):
let list_min xs =
match xs with
| [] -> None
| _ -> List.reduce min xs
|> Some
this way you get:
> list_min [2;1;5;3];;
val it : int option = Some 1
> list_min [2;1;5;3;0];;
val it : int option = Some 0
> list_min ([] : int list);;
val it : int option = None
ok it's a fair point that the question was about fold - so if it has to be exactly List.fold you can of course do (as TheInnerLight remarked):
let list_min xs =
match xs with
| [] -> None
| (x::xs) -> List.fold min x xs
|> Some

number_in_month exercise (Count elements in a list)

I have been trying to count elements in a list of integer 3-tuples, that equals a given integer using SML, but it's not working. Can anyone help me figure out what's wrong with the below code or straighten it up for me?
fun number_in_month(x : int*int*int list, m: int) =
if null x then 0
else
let fun inc x = x + 1;
in
val counter = 0;
if m = #2 (hd x) andalso m > 0 then inc counter
number_in_month((tl x), m)
` else
number_in_month((tl x), m)
end
This function is supposed to return the number of times m equals to the second element of each tuple in the list.
Clearly you have a hard time to let go of your imperative thinking.
Let me try and address some of your issues
You should be using pattern matching instead of using null x, hd x and tl x.
This also apply to decomposing tuples and records. For example
fun number_in_month ((x1, x2, x3) :: xs, m) = ...
or, since we don't ever use x1 and x3
fun number_in_month ((_, x2, _) :: xs, m) = ...
This way it is clearly seen that the first argument is a list of 3-tuples, and no type annotation
is needed
Also when you omit the explicit type annotation, which is the whole idea of having a type system
that can infer them for you (see next point), then this code
fun foo42 xs = map (fn x => #2 x) xs
will give you some nasty errors on "unresolved flex record" (this error message is from SML/NJ)
/tmp/sml20620PlF:105.5-105.44 Error: unresolved flex record
(can't tell what fields there are besides #2)
which is easily fixed by decomposing the 3-tuple
fun foo42 xs = map (fn (_, x2, _) => x2) xs
Speaking of type annotations. They are (almost always) not needed, and they clutter up the
readability of the code. Not to mention that they unnecessarily restricts the types you function
may be used on.
Also the type annotation you have given is erroneous according to what you really wan't. You
should have places parenthesis around the int * int * int. Currently it is interpreted as a
3-tuple of two ints and an int list int * int * (int list).
If you really insist in type annotating your function, then you can do it like this
val number_in_month : (int * int * int) list * int -> int =
fn ([] , m) => 0
| ((_,x2,_) :: xs, m) => 42
This is "almost" like Haskell, where the type is given just before the function declaration.
Try to be more consistent in they way you indent your code. That will give you better clarity.
Here I'm specifically thinking of the way you have indented the else part end the in ... end
part. The below part is clearly still erroneous in so many ways i can't begin to imagine, but it
gives an idea as how to do it
fun number_in_month(x : int*int*int list, m: int) =
if null x then 0
else
let fun inc x = x + 1;
in
val counter = 0;
if m = #2 (hd x) andalso m > 0 then
inc counter
number_in_month((tl x), m)
else
number_in_month((tl x), m)
end
You can't declare a variable val counter = 0 inside the in ... end part of a let-expression.
The semantics of a let-expression is
let
dec
in
exp_1; ...; exp_n
end
thus all declarations (function and value bindings, etc) must go in the let ... in part.
There is no need on earth to have an increment function, it just clutters the readability.
Remember that SML uses single assignment, thus variables are immutable after they are declared.
The sequence-thing inside your nested if-expression
inc counter
number_in_month((tl x), m)
makes absolutely no sense. The only way you can have more than one expression inside the
then ... else part (actually any place, where a single expression is expected), is with a
sequence (exp_1; ...; exp_n). However this is only usable when all but the last expression has
side effect(s), as their results is ignored/thrown away
- (print "Foo\n"; print "Bar\n"; 42);
Foo
Bar
val it = 42 : int
If you search a bit here on SO, you will see that a quite similar question has recently been asked and answered. Though it differs in the the type of the last argument, you might still get some useful pointers.
All in all a solution might look like
fun number_in_month ([], _) = 0
| number_in_month ((_,x2,_) :: xs, m) =
if x2 = m then
1 + number_in_month(xs, m)
else
number_in_month(xs, m)
However since your problem is simpler than the previously stated one, you could easily use some of the higher-order functions from the list module in the basis library
fun number_in_month (xs, m) = length (List.filter (fn (_, x2, _) => x2 = m) xs)
Or even (arguably) simpler, by folding over the list and incrementing a variable along the way each time it matches
fun number_in_month (xs, m) = foldl (fn ((_, x2, _), b) => if x2 = m then b+1 else b) 0 xs
fun number_in_month (L : (int*int*int) list, m : int) =
if L = nil
then 0
else
(if #2 (hd L) = m then 1 else 0) + number_in_month (tl L,m);
TESTING:
number_in_month ([] , 2);
number_in_month ([(1,2,3)] , 2);
number_in_month ([(1,2,3),(2,2,2)] , 2);
number_in_month ([(1,2,3),(2,2,2),(19,11,29)] , 2);
number_in_month ([(1,2,3),(2,2,2),(19,11,29),(10,28,19)] , 2);
number_in_month ([(1,2,3),(2,2,2),(19,11,29),(10,2,19)] , 2);
number_in_month ([(1,2,3),(2,2,2),(19,11,29),(10,28,19)] , 2);
number_in_month ([(1,2,3),(2,2,2),(19,11,29),(10,28,19)] , 2);
number_in_month ([(1,2,3),(2,2,2),(19,11,29),(10,28,19),(16,2,7)] , 2);
Reference:
http://www.cs.sunysb.edu/~leo/CSE215/smllistexamples.txt
http://www.standardml.org/Basis/list.html

SML list summing

I'm very new to SML and I am trying a list exercise. The goal is sum up the previous numbers of a list and create a new list. For example, an input list [1, 4, 6, 9] would return [1, 5, 11, 20].
This is my solution so far, but I think the issue is with how I'm defining the function.
fun rec sum:int list -> int list =
if tl(list) = nil then
hd(list)
else
hd :: sum((hd(tail) + hd(tl(list)))::tl(tl(list)));
Besides that you are using rec as a function name, then you have some minor issues to work on.
The explicit type annotation you have made is treated as an annotation of the function result.
Thus, according to what you have written, then it should return a function and not the expected
list. This is clearly seen from the below example:
- fun rec_ sum : int list -> int list = raise Domain;
val rec_ = fn : 'a -> int list -> int list
Your should be careful of using the head and tail functions, when you don't do any checks on the
number of elements in the list. This could be done with either the length function, or (even
easier and often better) by pattern matching the number of elements.
Your code contains sum as a function call and tail as an variable. The variable tail has never
been defined, and using sum as a function call, makes me believe that you are actually using rec
as a keyword, but don't know what it means.
The keyword rec is used, when defining functions using the val keyword. In this case, rec is
needed to be able to define recursive functions (not a big surprise). In reality, the keyword fun
is syntactic sugar (a derived form) of val rec.
The following 3 are examples of how it could have been made:
The first is a simple, straight forward solution.
fun sumList1 (x::y::xs) = x :: sumList1 (x+y::xs)
| sumList1 xs = xs
This second example, uses a helper function, with an added argument (an accumulator). The list is constructed in the reverse order, to avoid using the slow append (#) operator. Thus we reverse the list before returning it:
fun sumList2 xs =
let
fun sumList' [] acc = rev acc
| sumList' [x] acc = rev (x::acc)
| sumList' (x :: y :: xs) acc = sumList' (y+x :: xs) (x :: acc)
in
sumList' xs []
end
The last example, show how small and easy it can be, if you use the standard list functions. Here the fold left is used, to go through all elements. Again note that the list is constructed in the reverse order, thus it is reversed as the last step:
fun sumList3 [] = []
| sumList3 (x::xs) = rev (foldl (fn (a, b) => hd b + a :: b) [x] xs)
try this -
fun recList ([], index, sum) = []
| recList (li, index, sum) =
if index=0 then
hd li :: recList (tl li, index+1, hd li)
else
sum + hd li :: recList (tl li, index+1, sum + hd li)
fun recSum li = recList (li, 0, 0)
In your case -
recSum([1,4,6,9]) ;
will give
val it = [1,5,11,20] : int list
also don't use rec as fun name -it keyword .