(* parametric types in SML *) datatype ilist = E | L of int * ilist; val l = L(1, L(2, L(3, E))); (* returns the first element of a non-empty ilist *) fun first (L(h, _)) = h | first E = raise Match; first l; first E; (* returns the rest of a non-empty ilist *) fun rest (L(_, t)) = t | rest E = raise Match; rest l; fun last E = raise Match | last (L(h, E)) = h | last (L(h, t)) = last t; last l; (* a parametric list *) datatype 'a plist = E | L of 'a * 'a plist; fun first (L(h, _)) = h | first E = raise Match; fun rest (L(_, t)) = t | rest E = raise Match; fun last E = raise Match | last (L(h, E)) = h | last (L(h, t)) = last t; val l1 = L(1.0, L(2.0, E)); val l2 = L(1, L(2, E)); first l1; first l2; rest l1; rest l2; last l1; last l2; fun id x = x; id l1; id l2; fun toTriple x y z = (x,y,z); toTriple 1 2.0 (L(1,L(3,E))); toTriple 1 2.0 (L(1,L(3,L(9,L(27,E))))); (* Equality-testable types *) type T0 = int * real; type T1 = int * real; fun foo (s1:T1) (s2:T0) = (#1 s1, #2 s2); val x1:T0 = (1, 3.0); val x2:T1 = (2, 4.0); foo x1 x2; val ll1 = L(x2,E); val ll2 = L(x1, ll1); first ll1; first ll2; (* Paremeter coercion *) fun maxAux n E = n | maxAux n (L(h, t)) = if h > n then maxAux h t else maxAux n t; fun max E = raise Match | max (L(h, t)) = maxAux h t; fun inlinedMax E = raise Match | inlinedMax (L(h,t)) = let fun inlineMaxAux n E = n | inlineMaxAux n (L(h,t)) = if h > n then inlineMaxAux h t else inlineMaxAux n t; in inlineMaxAux h t end; max l1; max l2; inlinedMax l1; inlinedMax l2; fun max (a,b) = if a > b then a else b; (* Overloading in SML *) val a = 1 + 2; val b = 1.0 + 2.0;