FAQ
Some additional FAQs are answered here.
Do I need to end statements with semi-colons?
In Mitchell, as in Standard ML, semi-colons are optional at the end of declarations. They are required in only a few places.
Using the val _ = ...
construct for statements at the top-level and in let
expressions (even when a function is only called for its side-effect) is not
optional.
How do I modify a variable in Mitchell?
In Mitchell, variables cannot be modified. If you assign to a variable more than once, the later declaration will shadow the earlier one. For example, the following
val x = "goodbye\n"
val _ = let
val x = "hello\n"
in
print x
end
val _ = print x
will print
hello
goodbye
Several kinds of values in Mitchell are mutable, however. For example, even
though a variable that points to an array will always point to that array, the
array itself can be changed (e.g., using
Array.update
).
When you need to have a value of an arbitrary type that you can modify, you can
use ref
s. However, use of refs is discouraged. See this
documentation
for information on using ref
s.
Why does Mitchell say something is wrong at a spot in my code that looks fine?
Mitchell checks your code to make sure that you are using types of data in a consistent way. It reports errors where it finds a problem, but that isn’t always where the root cause of the problem is. Details on how to pin down a type error in your program can be found here.
How do I write tests in Mitchell?
There currently is no library to support unit testing in Mitchell.
However, anything that you write at the top-level in your .sml
file
(e.g., val _ = print “hello”
) will be
executed when you run your program with run-mitchell
.
That can be used to implement tests manually as a workaround.
How do I generate random numbers in Mitchell?
See the Mitchell
Random
library.
How do I print values?
See the libraries for converting data to strings.
What Standard ML functions are available in Mitchell?
Everything in the Standard Basis Library is available. Some functions are available without prefixing with the module name. You can see the list of those functions here.
For the purpose of this evaluation, we have included Standard ML libraries that is not supported on the hardware accelerators. Therefore, while you may write arbitrary Standard ML code as a Mitchell program, we ask that you keep any IO you do separate from your core algorithm implementation. This will allow us to re-target the implementation to the hardware accelerator for performance evaluation.
How to write a library in Mitchell?
You can build a library using Standard ML modules. See How Mitchell Builds on Standard ML for more information on using Standard ML constructs within Mitchell, and see this reference for information on the Standard ML module system.
What is the difference between Mitchell and Standard ML?
Mitchell is currently Standard ML with the addition of new libraries for machine learning and graph analytic, and with the removal of functionality that is not supported on hardware accelerators.
See /usr/local/bin/run-mitchell
for how Mitchell uses the MLton Standard ML
compiler.
What does this compiler error mean?
How do I get a value out of a pair or tuple?
There are two ways to use the invidivual values from a pair or tuple. One way is via pattern matching:
val pair = (42, "hello")
val (leftValue, rightValue) = pair
(* Now leftValue = 42 and rightValue = "hello" *)
The other way is to use the projection functions:
val pair = (42, "hello")
val leftValue = #1 pair
val rightValue = #2 pair
(* Now leftValue = 42 and rightValue = "hello" *)
Both ways extend to larger-sized tuples.
How do I get a value out of an array?
See the Array.sub
function in the Standard Basis Library.
How do I get the inferred type of a specific variable?
The easiest way to find out what type a variable was inferred to be is to
annotate it with the unit
type and get the inferred type from the error
message.
For example, compiling
val pair : unit = (42, 1.5)
Will produce the error
Pattern and expression disagree.
pattern: [unit]
expression: [int * real]
in: val pair: unit = (42, 1.5)
where int * real
is the inferred type of the variable.
How do I convert between numeric types?
For converting between int
and real
, see the
Real.toInt
and Real.fromInt
functions from the Standard Basis Library.
Numeric types of specific size (e.g., Real32.real
and Real64.real
) can be converted
between by converting to and from LargeReal.real
(using
Real<N>.toLarge
and
Real<N>.fromLarge
)
or LargeInt.int
(using
Int<N>.toLarge
and Int<N>.fromLarge
).
Similar functions are available for the word
types.