Introduction to ML

sml is installed on tux.cs.drexel.edu. You can run it by typing sml.
You can download and install ML from http://www.smlnj.org.

To exit Ml, type ctrl-D or OS.Process.exit(OS.Process.success);.
To load a file in the current directory type use "filename";
To load the file maxmin.ml from the current directory type use "maxmin.ml";

In ML, every line ends with a semicolon.
ML is strongly typed. The basic math functions work but only on inputs of the same type.

            - 2 + 3;
            val it = 5 : int
            - 5 - 7;
            val it = ~2 : int
            - 7 - 5;
            val it = 2 : int
            - 7 * 5;
            val it = 35 : int
            - 5 < 7;
            val it = true : bool
            - 5 * 1.1;
            stdIn:7.1-7.8 Error: operator and operand don't agree [literal]
                operator domain: int * int
                operand:         int * real
                in expression:
                5 * 1.1
        

Lists are available in ML. They are contained in square brackets and elements are seperated by commas.
[1, 2, 3, 4, 5];
The :: operator adds an element to the front of a list.
1 :: [2,3,4,5];
The hd function selects the first element in a list.
hd [1,2,3,4,5];
The tl function selects the tail of the list, every element but the head.
tl [1,2,3,4,5];
ML has very good pattern matching, so we can avoid these commands in most cases. The line below creates a variable where h is the head and t is the tail.

            - val h::t = [1,2,3,4];
            val h = 1 : int
            val t = [2,3,4] : int list
        
The null command detects if a list is null. We can avoid this command with pattern matching as well.
null [];

Function declaration and variable declaration are similar.
val L = [1,2,3,4];
fun sqr x = x * x;

We will again define functions recursively, there is an if command but it can be avoided in many cases.
if 1 < 2 then 5 else 7;
The definition for a factorial function using an if statement is given below.
fun fact n = if n = 0 then 1 else n * fact(n-1);
- fact 6;
val it = 720 : int

We can use pattern matching to define multple versions of the function. It is important we define the base case first. The patterns will be matched in order.

            fun fact2 0 = 1
            | fact2 n = n * fact2(n-1);
            fact2 10;
val it = 3628800 : int
We can use a the same idea to define append in two different ways.
Using patterns:
        fun append nil L = L
            | append (h::t) L = h::(append t L);
        
Using a case statement:
            fun append x y =
            case x of
                [] => y |
                (h::t) => h :: append t y;
            append [4] [1,2,3];
        

You can see the inputs of a function by typing its name with no inputs.
- hd;
val it = fn : 'a list -> 'a

The let command has the same functionallity as in scheme. It creates variables for immediate use instead of global variables.
let val a=5 val b=10 in a+b end;

ML allows libraries to be included. Additional list tools can be imported using open List;
This library will give access to commands like take, drop, and map.