Introduction to ML

Example code from ML for the Working Programmer (Paulson) and Elements of ML Programming (Ullman)
  • Standard ML Basis Library
  • Programming in Standard ML by Robert Harper, CMU (Current version in PDF)
    1. Most functional languages are interactive. If you enter an expression, the computer
      immediately evaluates and displays the results.
    2. To start ML: sml
    3. Type in an expresion of integers: 2 + 2;
      End the expression with a semicolon
      	- 2 + 2;
      	val it = 4 : int
      	
      	- 1 + 2 * 3;
      	val it = 7 : int
      
      	ML responds with the value and type of the variable "it" - a special
      	variable that receives the value of any expression in the interactive 
      	mode.
      
    4. Integers
      	- 0;
      	val it = 0 : int
      	
      	- 1234;
      	val it = 1234 : int
      	
      	- 11111111;
      	val it = 11111111 : int
      	
      	- ~1234;		Negative numbers begin with a tilde!
      	val it = ~1234 : int 
      	
      	- 0x1234;		Hexadecimal numbers begin with 0x
      	val it = 4660 : int
      
      
    5. Reals
      	- ~123.0;
      	val it = ~123.0 : real
      
      	- 3e~3;
      	val it = 0.003 : real
      	
      	- 3.14e12;
      	val it = 3.14E12 : real
      	
      	- 3.14159;
      	val it = 3.14159 : real
      	
      
    6. Booleans
      	
      	- true;
      	val it = true : bool
      	
      	- false;
      	val it = false : bool
      	
      	- 1=2;
      	val it = false : bool
      
    7. Strings
      	- "hello";
      	val it = "hello" : string
      	
      	- "hello world";
      	val it = "hello world" : string
      	
      	- print("h\tI\n");
      	h       I
      	val it = () : unit
      
    8. Characters: # followed by a string of length 1
      	- #"A";
      	val it = #"A" : char
      	
      	- #"\n";
      	val it = #"\n" : char
      
      
    9. Arithmetic operators
      	- 3.0 - 4.5 + 6.7 * 12.8;
      	val it = 84.26 : real
      
      	- 43 div (8 mod 3) * 5;
      	val it = 105 : int
      	
      	CAREFUL WITH MIXED MODE EXPRESSIONS!
      	
      	-  3.0 - 4.5 + 6.7 * 12;
      	 Error: operator and operand don't agree [literal]
      	  operator domain: real * real
      	  operand:         real * int
      	  in expression:  6.7 * 12
      
      
    10. String operators
      	- "house" ^ "cat";
      	val it = "housecat" : string
      
      
    11. Comparison Operators
      	- 2=2;
      	val it = true : bool
      	
      	- 2.0=2.0;	CAN'T COMPARE REALS WITH EQUALITY!
      	Error: operator and operand don't agree 
      	  operator domain: ''Z * ''Z   <- NOT SURE WHAT THIS MEANS
      	  operand:         real * real
      	  in expression:
      	    2.0 = 2.0
      
      	- #"Z" < #"a";
      	val it = true : bool
      	
      	- 2 < 1 + 3;
      	val it = true : bool
      
      	- 2 < 1;     
      	val it = false : bool
      
      	- "abc" < "ab";
      	val it = false : bool
      
      	- "Apple" < "apple";
      	val it = true : bool
      
      	- "apple" < "Apple";
      	val it = false : bool
      
      	- "abc" <= "ab";
      	val it = false : bool
      
      	- "abc" <= "ac";
      	val it = true : bool
      
      
    12. Combining logical values
      	- 1<2 orelse 3>4;
      	val it = true : bool
      	
      	- 1<2 andalso 3>4;
      	val it = false : bool
      
      	- not(1<2);
      	val it = false : bool
      
      
    13. If-Then-Else expressions (THERE ARE NO IF-THEN EXPRESSIONS!)
      	- if 1<2 then  3+4 else 5+6;
      	val it = 7 : int
      
      
    14. Coercion between types
      	- real(4);
      	val it = 4.0 : real
      
      	- real(1) + 2.0;
      	val it = 3.0 : real
      
      	- ord(#"A");
      	val it = 65 : int
      
      	- ord(#"a");        
      	val it = 97 : int
      
      	-  ord(#"a")- ord(#"A");
      	val it = 32 : int
      
      	- chr(65);
      	val it = #"A" : char
      
      	- str(#"a");
      	val it = "a" : string
      
      
    15. Assignment-like statement
      	- val pi = 3.14159;
      	val pi = 3.14159 : real
      
      	- pi;
      	val it = 3.14159 : real
      
      	- val radius=4.0;
      	val radius = 4.0 : real
      
      	- pi*radius*radius;
      	val it = 50.26544 : real
      
      	- val area =  pi*radius*radius;
      	val area = 50.26544 : real
      	
      	- area;
      	val it = 50.26544 : real
      
      	- val +-+-+ = 1234;   	Symbolic names can consist of ! % &  $ + - * /
      	val +-+-+ = 1234 : int				: < = > ? @ \ ~ ` ^ |
      	
      	- +-+-+;
      	val it = 1234 : int
      
      	- val ++ = 2;
      	val ++ = 2 : int
      
      	- val -- = 3;
      	val -- = 3 : int
      	
      	- ++ + --;
      	val it = 5 : int
      
      	- +-+-+ * +-+-+;
      	val it = 1522756 : int
      
      
      
    16. Special libraries
      	- Math.sin 0.5;
      	val it = 0.479425538604 : real
      
      	- Int.min(7, Int.sign 12);
      	val it = 1 : int
      
      	Also: round(), floor(), ceil(), trunc()
      
    17. Tuples: a tuple is formed by taking a list of two or more expressions of any types,
      separating them by commas, and surrounding them by parenthesis.
      	- (1,2);
      	val it = (1,2) : int * int
      
      	- (4, 5.0, "six");
      	val it = (4,5.0,"six") : int * real * string
      
      	- val t = (4, 5.0, "six");
      	val t = (4,5.0,"six") : int * real * string
      
      	- (1,2,3,4);
      	val it = (1,2,3,4) : int * int * int * int
      	
      	- (1,(2,3.0));
      	val it = (1,(2,3.0)) : int * (int * real)
      
      
    18. Accessing components of tuples
      	- #1(t);
      	val it = 4 : int
      
      	- #3(t);
      	val it = "six" : string
      
      
    19. Lists: a list of elements OF THE SAME TYPE, separated by commas, enclosed in square brackets.
      	- [1,2,3];
      	val it = [1,2,3] : int list
      
      	- ["a","b","c"];
      	val it = ["a","b","c"] : string list
      
      	- [(1,2),(3,4),(5,6)];
      	val it = [(1,2),(3,4),(5,6)] : (int * int) list
      
      	- [[1,2],[3,4],[5,6]];
      	val it = [[1,2],[3,4],[5,6]] : int list list
      
      
    20. List operators and operations
      	- val L = [2,3,4];
      	val L = [2,3,4] : int list
      
      	- val M = [5];
      	val M = [5] : int list
      
      	- hd(L);
      	val it = 2 : int
      
      	- tl(L);
      	val it = [3,4] : int list
      
      	- tl(M);
      	val it = [] : int list
      
      	- [1,2] @ [3,4];
      	val it = [1,2,3,4] : int list
      	
      	- 2::[3,4];
      	val it = [2,3,4] : int list
      
      	- 2.0::nil;
      	val it = [2.0] : real list
      
      	NOTE that :: separates a list into it's first and rest components,
      		it's car and cdr.  This is the same as hd() and tl().
      
    21. Defining functions
      	fun upper(c) = chr(ord(c)-32);
      	val upper = fn : char -> char
      
      	- upper(#"a");
      	val it = #"A" : char
      
      	TO LOAD A FUNCTION FROM A FILE: use "filename.ml"
      	This function would be typed into a file as
      	
      		fun upper(c) = chr(ord(c)-32);
      
      		or
      
      		fun upper(c) = 
      			chr(ord(c)-32);
      
    22. Type concerns when defining functions
      	- fun square(x:real) = x*x;
      	val square = fn : real -> real
      
      	- square(45.67);
      	val it = 2085.7489 : real
      
      	- square(45);
      	Error: operator and operand don't agree [literal]
      	  operator domain: real
      	  operand:         int
      	  in expression:  square 45
      
      	  - fun square(x) = x*x;      DEFAULTS TO INT
      	val square = fn : int -> int
      
      	- square(4567);
      	val it = 20857489 : int
      
      	fun max3(a:real, b, c) = (* maximum of 3 reals *)
      		if a>b then
      		    if a>c then a
      		    else c
      		else
      		    if b>c then b
      		    else c;
      		    
      	val max3 = fn : real * real * real -> real (ML respond with this line)
      
      	TWO VERSIONS OF REVERSE A LIST:
      	
      	fun reverse(L) =
      		if L = nil then nil
      		else reverse(tl(L)) @ [hd(L)];
      
      	fun reverse2(nil) = nil
      	|	reverse2(first::rest) = reverse2(rest) @ [first]
      
      
    23. Local declarations in functions
      	Reducing a fraction, version 1:
      	
      	fun gcd(m,n) =
      		if m=0 then n
      			else gcd(n mod m, m);
      		
      	fun fractionOne (n,d) = (n div gcd(n,d), d div gcd(n,d));
      
      	"fractionOne" uses two calls to the recursive gcd function
      
      	- fractionOne(1238,20004);
      	val it = (619,10002) : int * int
      
      	Version 2: using a local variable to store gcd(n,d)
      
      	fun fraction(n,d) =
      		let val com = gcd(n,d)
      		in (n div com, d div com) end;
      
      	
      	FORMAT OF "LET": let D in E end;
      
      	- fraction(1248,20004);
      	val it = (104,1667) : int * int