0% found this document useful (0 votes)
45 views

Types Polymorphic Functions

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views

Types Polymorphic Functions

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S

Types Polymorphic Functions


• primitive type : int, real, bool, unit, string, char, ..., list type, record type, • polymorphic functions can be applied to arguments of different types,
tuple type, function type; type abbreviation; datatype definition; polymorphic functions usually do something simple !
- fun ident x = x
in ML, the type for each expression is inferred and checked for val ident = fn : ’a -> ’a
consistency at compile time ! - fun pairself x = (x,x)
val pairself = fn : ’a -> ’a * ’a
- fun pairint (x : int) = (x,x)
if 1 < 2 then 3 else 4.0; val pairint = fn : int -> int * int
- fun fst (x,y) = x
type king = {name : string, val fst = fn : ’a * ’b -> ’a
born : int, - fun snd (x,y) = y
val snd = fn : ’a * ’b -> ’b
crowned : int, - val foo = pairself 4.0;
died : int, val foo = (4.0,4.0) : real * real
quote : string} - val bar = pairself “hello”;
val bar = (“hello”,”hello”) : string * string
- fst(foo);
fun lifetime(k : king) = #died k - #born k val it = 4.0 : real
- pairint(4.0);
fun fac n = if n = 0 then 1 else n * (fac(n-1)) std_in:13.1-13.12 Error: operator and operand don’t agree (tycon
mismatch) operator domain: int, operand: real, in expression:
pairint (4.0)

Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 1 of 20 Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 2 of 20

C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S

Polymorphic Data Structures More on Pattern Matching


infixr 5 :: • nested pattern --- use the “as” idiom
datatype ’a list = nil
| :: of ’a * ’a list
(* example : merging two sorted list of integers *)
fun rev nil = nil fun merge(x : int list, []) = x
| rev (a::r) = (rev r)@[a] | merge([], y) = y
val rev = fn : ’a list -> ’a list
| merge(x as (a::r), y as (b::z)) =
datatype ’a tree = LEAF of ’a if (a > b) then (b :: (merge(x, z)))
| NODE of ’a * ’a tree * ’a tree else if (a < b) then (a :: (merge(r, y)))
datatype ’a tree
con LEAF : ’a -> ’a tree else (a::(merge(r, z)))
con NODE : ’a * ’a tree * ’a tree -> ’a tree

fun depth(LEAF _) = 1 • partial record pattern --- must fully specify the record type !
| depth(NODE(_,left,right) = 1+max(depth(left),depth(right))
val depth = fn : ’a tree -> int
type king = {name : string, born : int, crowned : int,
val t = NODE(0, LEAF 1, LEAF 2) died : int, quote : string}
val t = NODE (0,LEAF 1,LEAF 2) : int tree

- depth t; fun lifetime ({born, died, ...} : king) = died - born


val it = 2 : int

Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 3 of 20 Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 4 of 20
C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S

Higher-Order Functions Exceptions


• In ML, functions can be passed as arguments, returned as the result, exception con
or exception con of ty
and even stored in a data structure
5 div 0;
uncaught exception Div
fun map f nil = nil
| map f (a::r) = (f a)::(map f r) exception NotFound of string;
val map = fn : (’a -> ’b) -> (’a list -> ’b list) type dictionary = (string * string) list
fun lookup ([],s)= raise (NotFound s)
| lookup ((a,b)::r,s : string) =
fun map2 f = if (a=s) then b else lookup(r,s)
(let fun m nil = nil
| m (a::r) = (f a)::(m r) val sampleDict = [(“foo”, “a sample name”),
in m (“bar”, “another sample name”)]
end) val x = lookup(sampleDict, “foo”);
val map2 = fn : (’a -> ’b) -> (’a list -> ’b list) val x = “a sample name” : string

(* composing two functions *) val y = lookup(sampleDict, “moo”);


fun comp (f,g) = (fn x => g(f(x))) uncaught exception NotFound
val comp = fn : (’a -> ’b) * (’b -> ’c) -> (’a -> ’c)
val z = lookup(sampleDict, “moo”) handle NotFound s =>
(print (“cannot find ”^s^“ in the dict”); “a word”)
val z = “a word” : string

Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 5 of 20 Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 6 of 20

C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S

Input and Output Assignment via References


structure TextIO (* read the basis manual on the web *) • ML supports updatable refernce cells

type instream (* the input stream *) (* assignment operator “:=”, dereference “!” *)
type outstream (* the output stream *) let val lineNum = ref 0 (* has type int ref *)
in lineNum := !lineNum + 1;
val stdIn : instream (* the standard input stream *)
val stdOut : outstream (* the standard output stream *)
lineNum := !lineNum + 1;
val stdErr : outstream (* the standard error output stream *) lineNum
end
val openIn : string -> instream (* open a file for input *)
val openOut : string -> outstream (* open a file for output *)
val openAppend : string -> outstream (* open a file for appending*) • Assignement is different from value binding
val closeIn : instream -> unit (* close a input file *) just a value !
val closeOut : outstream -> unit (* close a output file *) local val x = 1
in fun new1() = let val x = x+1 in x end
val output : outstream * string -> unit
end
val input : instream -> string a pointer to a memory cell !
val inputLine : instream -> string local val x = ref 1
............ in fun new2() = (x := !x + 1; !x)
end

Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 7 of 20 Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 8 of 20
C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S

ML Module --- “Structure” Module Interface --- “Signature”


structure Ford = signature MANUFACTURER =
struct sig
type car = {make : string, built : int} type car
val first = {make = “Ford”, built = “1904”} val first : car
fun mutate (c : car) year = val built : car -> int
{make = #make c, built = year} val mutate : car -> int -> car
fun built (c : car) = #built c val show : car -> string
fun show (c) = if (built c) < (built first) end
then “ - ” else “(generic Ford)”
end signature YEAR =
sig
structure Year = eqtype year
struct val first : year
type year = int val second : year
val first = 1900 val new_year : year -> year
val second = 2000 val show : year -> string
fun new_year(y : year) = y+1 end
fun show(y : int) = makestring(y)
end signature MSIG = A signature is a collection
A structure is an sig of specifications for types,
structure MutableCar = structure C : MANUFACTUER
struct structure C = Ford
encapsulated collection of structure Y : YEAR values and structures ...
structure Y = Year declarations ! end
end

Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 9 of 20 Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 10 of 20

C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S

Structure Matching Functors


• a structure S matches a signature SIG if every component • A functor is a parametrized module. It takes a structure as argument
specification in SIG is matched by a component in S. and return another structure as the result !

• S can contain more components than SIG !!!


functor ProductLine(M : MANUFACTURER) =
structure Year1 : YEAR =
struct struct
type year = int fun line(y,c) =
val first = 1900 if y = 2000 then ()
val second = 2000 else (output(std_out, (“\n” ^ (Int.toString y)
fun new_year(y : year) = y+1
fun decade y = (y - 1900) div 10 ^ “\t” ^ M.show c));
fun show(y : int) = line(y+1, M.mutate c (y+1))
if y < 1910 orelse y >= final )
then Int.toString(y) fun show() = line(M.built M.first, M.first)
else (“the ’”^(Int.toString (decade y))^“0s”)
end end
use “long identifier” to refer
val long_gone = Year1.show 1968 to the structure component. structure FordLine = ProductLine(Ford)
val _ = FordLine.show();
structure MCar : MSIG = MutableCar OR use the identifier directly
val long_gone2 = MCar.Y.show 1968 after the structure is “open-ed”

Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 11 of 20 Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 12 of 20
C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S

How to Use CM “tiger.lex” skeleton


• CM inside sml is just like “make”. type pos = int
type lexresult = Tokens.token
• the standard makefile is sources.cm
val lineNum = ErrorMsg.lineNum
(* sources.cm for assignment 2 *) val linePos = ErrorMsg.linePos
Group is fun err(p1,p2) = ErrorMsg.error p1
driver.sml fun eof() = let val pos = hd(!linePos)
errormsg.sml in Tokens.EOF(pos,pos)
tokens.sig end
tokens.sml
tiger.lex %%
/c/cs421/lib/smlnj-lib.cm %%
.lex ML-Lex source .grm ML-Yacc source .cm library inclusion
\n => (inc lineNum; linePos := yypos :: !linePos;
.sml, .sig SML source continue());
“,” => (Tokens.COMMA(yypos,yypos+1));
var => (Tokens.VAR(yypos,yypos+3));
• after enter sml, type CM.make(); “123” => (Tokens.INT(123,yypos,yypos+3));

Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 13 of 20 Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 14 of 20

C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S

“tokens.sig” “tokens.sml”
signature Toy_TOKENS = structure Tokens : Toy_TOKENS =
sig struct
type linenum (* = int *) (* A “scaffold” structure for debugging lexers. *)
type token val makestring = Int.toString
val TYPE: linenum * linenum -> token type linenum = int
val VAR: linenum * linenum -> token type token = string
val FUNCTION: linenum * linenum -> token fun TYPE(i,j) = “TYPE “ ^ makestring(i:int)
val BREAK: linenum * linenum -> token fun VAR(i,j) = “VAR “ ^ makestring(i:int)
............ fun FUNCTION(i,j) = “FUNCTION “ ^ makestring(i:int)
val DOT: linenum * linenum -> token fun BREAK(i,j) = “BREAK “ ^ makestring(i:int)
val RBRACE: linenum * linenum -> token fun OF(i,j) = “OF “ ^ makestring(i:int)
val LBRACE: linenum * linenum -> token fun END(i,j) = “END “ ^ makestring(i:int)
val RBRACK: linenum * linenum -> token fun IN(i,j) = “IN “ ^ makestring(i:int)
val LBRACK: linenum * linenum -> token fun NIL(i,j) = “NIL “ ^ makestring(i:int)
val RPAREN: linenum * linenum -> token fun LET(i,j) = “LET “ ^ makestring(i:int)
val LPAREN: linenum * linenum -> token fun DO(i,j) = “DO “ ^ makestring(i:int)
val SEMICOLON: linenum * linenum -> token fun TO(i,j) = “TO “ ^ makestring(i:int)
val COLON: linenum * linenum -> token fun FOR(i,j) = “FOR “ ^ makestring(i:int)
val COMMA: linenum * linenum -> token ................
val STRING: (string) * linenum * linenum -> token ................
val INT: (int) * linenum * linenum -> token fun STRING(s,i,j) = “STRING(“^s^ “) “ ^ makestring(i:int)
val ID: (string) * linenum * linenum -> token fun ID(s,i,j) = “ID(“^s^“) “ ^ makestring(i:int)
val EOF: linenum * linenum -> token fun EOF(i,j) = “EOF “ ^ makestring(i:int)
end end

Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 15 of 20 Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 16 of 20
C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S

“errormsg.sml” “errormsg.sml” (cont’d)


signature ERRORMSG = structure ErrorMsg : ERRORMSG =
sig struct
val anyErrors : bool ref ........
val fileName : string ref exception Error
val lineNum : int ref val makestring = Int.toString
val linePos : int list ref
val sourceStream : TextIO.instream ref fun error pos (msg:string) =
val error : int -> string -> unit let fun look(p:int,a::rest,n) =
exception Error if a<p then app print [“:”,makestring n,
val impossible : string -> ‘a (* raises Error *) ”.”,makestring (p-a)]
val reset : unit -> unit else look(p,rest,n-1)
end | look _ = print “0.0”
in anyErrors := true;
structure ErrorMsg : ERRORMSG = print (!fileName);
struct look(pos,!linePos,!lineNum);
val anyErrors = ref false print “:”;
val fileName = ref ““ print msg;
val lineNum = ref 1 print “\n”
val linePos = ref [1] end
val sourceStream = ref std_in
fun impossible msg = ......
fun reset() = ...
exception Error end (* structure ErrorMsg *)
........

Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 17 of 20 Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 18 of 20

C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S C S 4 2 1 C O M P I L E R S A N D I N T E R P R E T E R S

“driver.sml” Assignment 2
structure Parse =
struct Writing a lexical analyzer for Tiger using ML-Lex
structure Lex = Mlex

fun parse filename =


let val file = TextIO.openIn filename
fun get _ = TextIO.input file • how to handle nested comments ?
val lexer = Lex.makeLexer get
• how to handle string literals, integer literals, identifiers ?
fun do_it() =
let val t = lexer()
in print t; print “\n”; • how to do the error handing especially for unclosed comments or strings
if substring(t,0,3)=”EOF” then () else do_it()
end (at the end of the file) ?

in do_it();
TextIO.closeIn file
end
end

Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 19 of 20 Copyright 1994 - 2005 Zhong Shao, Yale University More on ML: Page 20 of 20

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy