180 likes | 333 Views
SML-97 Specifics. SML/NJ 110. Invoking interpreter (actually a compiler in interactive mode!) % sml Loading ML program - use “~/eg.sml”; Accessing a structure element Int.max; Opening a structure open Real;.
E N D
SML-97 Specifics SML/NJ 110 L4-SML
Invoking interpreter (actually a compiler in interactive mode!) % sml Loading ML program - use “~/eg.sml”; Accessing a structure element Int.max; Opening a structure open Real; Top-level environment contains a selected set of useful functions. A more complete set of standard functions is organized into structures (Int, Real, String, etc) that forms the standard basis. - Real.Math.sqrt(4.0) - List.take(2,[1,2,3]) Getting Started L4-SML
~ 1 + 21 ; val it = 20 : int; “1\t\na\t\n”; tab, newline,… “\\\”” ^ “abc”; Slash, double quotes, concatenation - #“a”; character #“Z” < #“a” ; “abd” < “ac”; 1 <> 2; 1<2 orelse 1.0/0.0; if true andthen not (1>=2) then 3.0 else 3.142 ; if-thencontrol structure is legal, but not expression. Expressions L4-SML
1 + 2.0; No coercion real(1) + 2.0; 1 + floor(2.0); 1/2; #“a” ^ “bb”; if true then #“a” else “bb”; 1::[2.0]; real is not an equality type. Portability reasons. (Cf. (int->int) is not an equality type for computability reasons.) In the absence of rounding errors, (r=s) is equivalent to (r<=s) andalso (s<=r). “Tip of the” Type Errors L4-SML
Identifiers • Alphanumeric Identifiers a’1_b2, B2_bomber, …, etc • ordinary variables ’a’b’c, ’’a, etc • type variables • Symbolic Identifiers <>=, @%$#, |?:&, +, /, etc • Separators ( , ) , [ ,] ,{ ,} , ” , . , , , ; ML is case-sensitive. L4-SML
Variables • Identifiers vs Variables vs Values • Environment vs Store • Adding new variable and binding val i = 10; val i = [1,2,3]; (Cf., “:=” in Pascal and “=” in C.) • Static scoping (Closure) val a = 2; fun ax(x) = a * x; val a = 5; ax 10; (* ax 10 = 20 *) L4-SML
Patterns fun merge (L as x::xs, M as y::ys) = … fun comb(_,0) = … fun f ((x,y)::z::xs) = … Illegal cases: fun length (xs @ [x]) = … fun f (x+1) = … fun g (0.0) = … Term Matching (cf. Unification) L4-SML
fun same (n,n) = 0 | same _ = 1; Error: duplicate variable in pattern (* requires equational reasoning *) fun fp nil = 0 | fp (x::xs) = 1; val fp = fn : 'a list -> int fun feq xs = if (xs = nil) then 0 else 1; val feq = fn : ''a list -> int L4-SML
Match Expressions val rec reverse = fn nil => nil | x::xs => reverse(xs) @ [x] ; rule : pattern => expression case x < y of true => x | false => y ; if x < y then #“1” else 1; Error: Type of rules do not agree. L4-SML
Skip what follows L4-SML
Limitations on the use of polymorpic functions fun id x = x;(* id :’a -> ’a *) id 0;(* id : int -> int *) idid 0;(* id :(int -> int) -> (int -> int) *) val id = fn x => x; (* id :’a -> ’a *) To ensure that a bound variable has the same meaning as its binding, the variable introduced by a val-declaration is allowed to be polymorphic only if the right-hand side is a value (and not a computation). L4-SML
val J = id id; (*illegal*) Motivation: Contexts (such as (J 5, J “a”) )that replicate the binding may impose conflicting requirements on the type. • (cf. Multiple evaluation of side-effect causing expressions.) • (cf. Referential transparency violated if two occurrences of an expression is not equivalent to two occurrences of its value.) Value Restriction is too conservative. val k = nil @ nil; (* illegal *) L4-SML
Value Restriction on Polymorphic Declaration ILLEGAL: id id; id foldr; LEGAL: fun J x = id id x; id id “a”; id Int.max; let val v = id id in v “a” end; L4-SML
Polymorphic type variable: ’a • Generalizable (universal quantification) for every type T, there is an instance of this object • Non-generalizable (existential quantification) there exists a fixed but arbitrary type T for this object For compile-time guarantees, SML-97 requires that the expressions at the top-level be such that the generalizable interpretation of type variables is appropriate. L4-SML
Non-expansive Expressions • A constant or a variable is non-expansive. • A function definition is non-expansive. • A tuple of non-expansive expressions is non-expansive. • A non-expansive expression may be preceded by a data/exception constructor. • Expressions that are not of these forms are expansive and are not allowed to have type variables. • Generates a “type variable not generalizable” error. L4-SML
Non-generalizable type variable error • All the following conditions must be met for the error to occur: • The expression is at the top-level. • The type of the expression involves at least one type variable. • The form of the expression does not meet the conditions for it to be non-expansive. L4-SML
Examples • id id ; (* error *) • (id, id) ; • val it = <poly-record> : ('a -> 'a)*('b -> 'b) • id (id:int-> int) ; • [id, id] • val it = [fn,fn] : ('a -> 'a) list (* Allowed by SML97 even though according to Ullman’s book it is illegal? *) L4-SML
(cont’d) • let val x = (id id) in x(1) end; (* Legal. (id id) is not top-level. *) • let val x = (id id) in (x 1, x “a”) end; (* Error: operator and operand don't agree.*) • (id 1, id “a”) ; (* val it = (1,"a") : int * string *) • let val x = id in (x 1, x “a”) end; L4-SML