What does val it = () : unit mean in SML? - sml

I've never programmed in SML before, and I'm using SML/NJ. It keeps giving me the following at the end of each program I run:
val it = () : unit
What does this mean? Is it something I'm doing wrong?

it is the name of the result returned by your code. () : unit is a trivial placeholder value returned from things that are side-effect based.
It's more obvious when you enter something that's more commonly an expression at the prompt, e.g...
- 2 * 7;
val it = 14 : int

You can also use it for the side effect of printing things out:
fun printpos n =
if n <= 0 then (print "not positive!\n")
else (print (Int.toString n); print "\n");
printpos ~1;
printpos 1;
(* Output:
val printpos = fn : int -> unit
not positive!
val it = () : unit
1
val it = () : unit
*)

Related

How to wait for Concurrent ML threads to finish before exiting program?

I am attempting to implement a basic 'stress testing' program in MLton and its Concurrent ML implementation, specifically the Monte Carlo Pi test described here. While I think I have most of what I need figured out, I have a problem in that my program always terminates before the CML threads have finished their work. I know that they are doing something, since I sometimes see them print text to the console that I have directed should be printed, but there seems to be a race condition between them getting started and running, and the program as a whole exiting.
The code where I start CML is:
local
val iterations : int = 10
val num_threads : int = 1
val still_going : bool ref = ref true
in
val _ = (RunCML.doit ((experiment iterations num_threads still_going), NONE);
(* while !still_going do (); (* Spin-wait for the CML stuff to finish. This doesn't work... *) *)
print "All done!\n")
end
the contents of the experiment function are:
fun experiment (iterations : int) (num_threads : int) (still_going : bool ref) () : unit = let
val iters_per_thread : int = iterations div num_threads
val return_ivars = Vector.tabulate (num_threads, (fn _ => SyncVar.iVar()))
val _ = Vector.map (fn return_ivar => CML.spawn (montecarlopi iters_per_thread return_ivar)) return_ivars
val return_val = Vector.foldl (fn (elem, acc) => acc + (SyncVar.iGet elem)) 0.0 return_ivars
in
(TextIO.print ("Result is: " ^ (Real.toString return_val) ^ "\n");
still_going := false)
end
and finally, the montecarlopi function is:
fun montecarlopi (iterations : int) (return_ivar : real SyncVar.ivar) () = let
val _ = MLton.Random.srand (valOf (MLton.Random.useed ()))
fun helper accumulator 0 = accumulator
| helper accumulator iteration = let
val x : real = wordToBoundedReal (MLton.Random.rand ())
val y : real = wordToBoundedReal (MLton.Random.rand ())
val in_target = (x * x) + (y * y)
val next_iter = iteration - 1
val _ = TextIO.print ("next_iter is: " ^ (Int.toString next_iter) ^ ", in_target is: " ^ (Real.toString in_target) ^ ",x is: " ^ (Real.toString x) ^ ",y is: " ^ (Real.toString y) ^ "\n")
in
if in_target < 1.0 then
helper (accumulator + 1) next_iter
else
helper accumulator next_iter
end
in
SyncVar.iPut (return_ivar, (4.0 * ((real (helper 0 iterations)) / (real iterations))))
end
(The full (small) program and accompanying .mlb file can be viewed here). I'm reasonably sure that the bits inside the RunCML.doit function call do what they're supposed to, which leads me to think that the issue is probably to do with the outermost part of the program.
As you can see, I tried to spin wait, using a ref cell on a boolean to determine when to stop, but that doesn't seem to work. Nor does trying to spin wait using RunCML.isRunning - although both of those sound like terrible ideas to begin with, really, anyway. Of course, I can't use something like a CML channel or syncvar, since those need to be inside the RunCML.doit segment to be used. Changing the number of threads doesn't make any difference to this problem. Nor was I able to find any other functions that would make the main part go into a non-blocking wait.
How do I get the outer part of my program to wait until the bulk of it, inside the RunCML.doit function call, completes? Or, am I doing something wrong inside that part, which is causing the problem?
If we look at the the function RunCML.doit, It has type OS.Process.status which can either be success or failure, from which your call to doit is returning failure. There is a CML function shutdown: OS.Process.status -> 'a.
Which could be an explaination for why it's failing, except you don't call shutdown, and parts of your output results never print.
Here is a small example exercising various mechanisms for CML's shutdown, where CML seems to be doing something such as 'graceful' internally. Catching exceptions raised and turning those into failure.
structure Main = struct
open CML
structure RunCML = RunCML;
exception ohno
fun raises() = raise ohno
fun succeed() = RunCML.shutdown(OS.Process.success)
fun fail() = RunCML.shutdown(OS.Process.failure)
fun graceful f () =
let val () = f() handle _ => RunCML.shutdown(OS.Process.failure);
in RunCML.shutdown(OS.Process.success)
end
fun print_status status =
if OS.Process.isSuccess status
then TextIO.print("success\n")
else TextIO.print("failure\n")
fun main() = let
val _ = TextIO.print(banner ^ "\n");
val _ = print_status(RunCML.doit(succeed, NONE))
val _ = print_status(RunCML.doit(fail, NONE))
val _ = print_status(RunCML.doit(raises, NONE))
val _ = print_status(RunCML.doit(graceful(raises), NONE))
val _ = print_status(RunCML.doit(graceful(succeed), NONE))
in OS.Process.success end
end
So, if CML is exiting strangely, and you aren't calling shutdown yourself, its a good chance there is an exception being raised somewhere, which turned out to be the case.
One way to avoid this silent handling of exceptions might in the future might be adding something like:
fun noisy f () =
let val () = f()
handle e =>
let val () = TextIO.print ("Exception: " ^ (exnName e)
^ " Message: " ^ (exnMessage e) ^ "\n")
in RunCML.shutdown(OS.Process.failure) end
in RunCML.shutdown(OS.Process.success)
end
then calling RunCML.doit(noisy(f), NONE)
P.S. Thank you for including a link to your code, it would have been much harder to understand the problem otherwise.

Simple function with internal state

I would like to write a minimal function with an internal state.
It should have signature f: () -> () and the n-th time it is called should print the number n.
I imagine that refs are necessary, but I do not know how to use them to make such a function.
I found a solution with an external local reference
local val mem = ref 0 in
fun f () =
let val _ = mem := !mem + 1 in print (Int.toString (!mem)) end
end
A solution to a slightly different problem would be to generate the function
fun iter_int n =
let val i = ref 0
in fn () =>
let val j = !i
in i := !i + 1 ; j
end
end

Function that takes type unit

I'm trying to create a function that has the type:
unit -> (int list * int list * int list)
But I was wondering, unit is an empty type (has no value), so how would it be possible to do something with it and return 3 int lists?
Thanks
The type unit is not empty.
It has one value which is spelled () and is usually called "unit", like its type.
(One meaning of the word "unit" is "a single thing".)
Example:
- ();
val it = () : unit
- val you_knit = ();
val you_knit = () : unit
- fun foo () = ([1], [2], [3]);
val foo = fn : unit -> int list * int list * int list
- foo ();
val it = ([1],[2],[3]) : int list * int list * int list
- foo you_knit;
val it = ([1],[2],[3]) : int list * int list * int list
(Note that () is not an empty parameter list; ML doesn't have parameter lists.)
Strictly speaking, the above definition pattern-matches on the value ().
Without pattern matching, it could look like this:
- fun bar (x : unit) = ([1], [2], [3]);
val bar = fn : unit -> int list * int list * int list
- bar ();
val it = ([1],[2],[3]) : int list * int list * int list
In SML type unit often represents an input/output action or more generally something which involves side effects. A somewhat realistic example of a function of the sort you are looking for would be one which returns 3 randomly generated lists. Another example would be one which pulls numbers from standard input something like:
open TextIO
fun split s = String.tokens (fn c => c = #",") s
fun toInt s = valOf (Int.fromString s)
fun toIntList line = map toInt (split line)
fun getInts prompt =
(
print prompt;
case inputLine(stdIn) of
SOME line => toIntList line |
NONE => []
)
fun getLists() =
let
val prompt = "Enter integers, separated by a comma: "
in
(getInts prompt, getInts prompt, getInts prompt)
end
The type of getLists is
val getLists = fn : unit -> int list * int list * int list
a typical "run" of getLists:
- getLists();
Enter integers, separated by a comma: 1,2,3
Enter integers, separated by a comma: 4,5,6
Enter integers, separated by a comma: 7,8,9
val it = ([1,2,3],[4,5,6],[7,8,9]) : int list * int list * int list

How do I test for an error in Haskell?

I want to be able to make sure a function will throw an error when it receives and invalid value. For example, let says I have a function pos that only returns a positive number:
pos :: Int -> Int
pos x
| x >= 0 = x
| otherwise = error "Invalid Input"
This is a simplistic example, but I hope you get the idea.
I want to be able to write a test case that will expect an error and consider it a passing test. For example:
tests = [pos 1 == 1, assertError pos (-1), pos 2 == 2, assertError pos (-2)]
runTests = all (== True) tests
[My Solution]
This is what I ended up going with based on #hammar's comment.
instance Eq ErrorCall where
x == y = (show x) == (show y)
assertException :: (Exception e, Eq e) => e -> IO a -> IO ()
assertException ex action =
handleJust isWanted (const $ return ()) $ do
action
assertFailure $ "Expected exception: " ++ show ex
where isWanted = guard . (== ex)
assertError ex f =
TestCase $ assertException (ErrorCall ex) $ evaluate f
tests = TestList [ (pos 0) ~?= 0
, (pos 1) ~?= 1
, assertError "Invalid Input" (pos (-1))
]
main = runTestTT tests
OP's solution defines assertException, but it looks like Test.HUnit.Tools.assertRaises from testpack is also usable here.
I added the msg argument to assertError to match how assertRaises works, and included selective imports so noobs like me can learn where commonly used things are imported from.
import Control.Exception (ErrorCall(ErrorCall), evaluate)
import Test.HUnit.Base ((~?=), Test(TestCase, TestList))
import Test.HUnit.Text (runTestTT)
import Test.HUnit.Tools (assertRaises)
pos :: Int -> Int
pos x
| x >= 0 = x
| otherwise = error "Invalid Input"
instance Eq ErrorCall where
x == y = (show x) == (show y)
assertError msg ex f =
TestCase $ assertRaises msg (ErrorCall ex) $ evaluate f
tests = TestList [
(pos 0) ~?= 0
, (pos 1) ~?= 1
, assertError "Negative argument raises an error" "Invalid Input" (pos (-1))
]
main = runTestTT tests
There are several ways to handle errors in Haskell. Here is an overview: http://www.randomhacks.net/articles/2007/03/10/haskell-8-ways-to-report-errors
[Edit]
The first example shows how to catch errors, e.g.
half :: Int -> Int
half x = if even x then x `div` 2 else error "odd"
main = do catch (print $ half 23) (\err -> print err)
That said, this kind of error handling is better suited for IO stuff, in pure code like yours Maybe, Either or something similar is usually a better choice. It could be as simple as...
pos :: Int -> Maybe Int
pos x
| x >= 0 = Just x
| otherwise = Nothing
tests = [pos 1 == Just 1
,pos (-1) == Nothing
,pos 2 == Just 2
,pos (-2) == Nothing
]
main = print $ and tests
... if you don't need an error type.

SML how to get while on char list to return int?

I'm having a bit difficulty figuring out, how to get each of the processed chars back to an int value.
The function should work like: val caesar = fn : int * int -> int
So if k = 2466 and n = 2, then the output should be 4688
Hope the code isn't too weird (I'm a SML newbie).
(* Load Libs *)
load "Int";
load "Real";
load "String";
load "Char";
load "List";
fun caesar (k, n) =
let
fun k_string (i) = Int.toString(i)
fun item_k_char (x, y) = Char.ord (List.nth (x, y))
val val_k_string = k_string(k)
val k_explode = String.explode(val_k_string)
val counter = ref 0
val counter_end = (String.size(val_k_string) - 1)
in
while (!counter >= counter_end) do (
item_k_char(k_explode, !counter) + n;
counter := !counter + 1
)
end;
A while loop isn't the best tool here. Instead you can use map which executes a given function for each item in a given list and returns a new list containing the result of each call to the function.
In other words: map (fn c => (Char.ord c) + 2) [#"2", #"4", #"6", #"6"] will return [52,54,56,56]. You can the convert this back to char and use String.implode to get the string "4688".
You probably also want to add some logic so that the numbers "wrap around", i.e. caesar (7,7) becomes 4.
So all in all your code becomes:
fun caesar (k, n) =
let
val val_k_string = Int.toString k
val k_explode = String.explode val_k_string
val ints = map (fn c => (Char.ord c) + n) k_explode
val wrappedAroundInts = map (fn i => (i - 48) mod 10 + 48) ints
val chars = map Char.chr wrappedAroundInts
val string = String.implode chars
in
Option.valOf (Int.fromString string)
end