Unformatted text preview:

281CS 538 Spring 2006©Power Sets RevisitedLet’s compute power sets in ML.We want a functionpow that takes alist of values, viewed as a set, andwhich returns a list of lists. Eachsublist will be one of the possiblesubsets of the original argument.For example,pow [1,2] = [[1,2],[1],[2],[]]We first define a version of cons incurried form:fun cons h t = h::t;val cons = fn : 'a -> 'a list -> 'a list282CS 538 Spring 2006©Now we define pow. We define thepowerset of the empty list,[], to be[[]]. That is, the power set of theempty set is set that contains onlythe empty set.For a non-empty list, consisting ofh::t, we compute the power set of t,which we callpset. Then the powerset forh::t is just h distributedthroughpset appended to pset.We distributeh through pset veryelegantly: we just map the function(cons h) to pset. (cons h) adds hto the head of any list it is given.Thus mapping(cons h) to psetadds h to all lists in pset.283CS 538 Spring 2006©The complete definition is simplyfun pow [] = [[]] | pow (h::t) = let val pset = pow t in (map (cons h) pset) @ pset end;val pow = fn : 'a list -> 'a list listLet’s trace the computation ofpow [1,2].Hereh = 1 and t = [2]. We need tocomputepow [2].Nowh = 2 and t = [].We knowpow [] = [[]],sopow [2] =(map (cons 2) [[]])@[[]] =([[2]])@[[]] = [[2],[]]284CS 538 Spring 2006©Therefore pow [1,2] =(map (cons 1) [[2],[]])@[[2],[]] =[[1,2],[1]]@[[2],[]] =[[1,2],[1],[2],[]]285CS 538 Spring 2006©Composing FunctionsWe can define a composition functionthat composes two functions intoone:fun comp (f,g)(x) = f(g(x));val comp = fn :('a -> 'b) * ('c -> 'a) -> 'c -> 'bIn curried form we havefun comp f g x = f(g(x));val comp = fn :('a -> 'b) ->('c -> 'a) -> 'c -> 'bFor example,fun sqr x:int = x*x;val sqr = fn : int -> intcomp sqr sqr;val it = fn : int -> int286CS 538 Spring 2006©comp sqr sqr 3;val it = 81 : intIn SML o (lower-case O) is the infixcomposition operator.Hencesqr o sqr ≡ comp sqr sqr287CS 538 Spring 2006©Lambda TermsML needs a notation to write downunnamed (anonymous) functions,similar to the lambda expressionsScheme uses.That notation isfn arg => body;For example,val sqr = fn x:int => x*x;val sqr = fn : int -> intIn fact the notation used to definefunctions,fun name arg = body;is actually just an abbreviation for themore verboseval name = fn arg => body;288CS 538 Spring 2006©An anonymous function can be usedwherever a function value is needed.For example,map (fn x => [x]) [1,2,3];val it =[[1],[2],[3]] : int list listWe can use patterns too:(fn [] => [] |(h::t) => h::h::t);val it = fn : 'a list -> 'a list(What does this function do?)289CS 538 Spring 2006©Polymorphism vs. OverloadingML supports polymorphism.A function may accept a polytype (aset of types) rather than a singlefixed type.In all cases, the same functiondefinition is used. Details of thesupplied type are irrelevant and maybe ignored.For example,fun id x = x;val id = fn : 'a -> 'afun toList x = [x];val toList = fn : 'a -> 'a list290CS 538 Spring 2006©Overloading, as in C++ and Java,allows alternative definitions of thesame method or operator, withselection based on type.Thus in Java+ may represent integeraddition, floating point addition orstring concatenation, even thoughthese are really rather differentoperations.In ML+, -, * and = are overloaded.When= is used (to test equality), MLdeduces that an equality type isrequired. (Most, but not all, types canbe compared for equality).When ML decides an equality type isneeded, it uses a type variable thatbegins with two tics rather than one.fun eq(x,y) = (x=y);val eq = fn : ''a * ''a -> bool291CS 538 Spring 2006©Defining New Types in MLWe can create new names for existingtypes (type abbreviations) usingtype id = def;For example,type triple = int*real*string;type triple = int * real * stringtype rec1= {a:int,b:real,c:string};type rec1 = {a:int, b:real, c:string}type 'a triple3 = 'a*'a*'a;type 'a triple3 = 'a * 'a * 'atype intTriple = int triple3;type intTriple = int triple3These type definitions are essentialitymacro-like name substitutions.292CS 538 Spring 2006©The Datatype MechanismNew types are defined using thedatatype mechanism, whichspecifies new data value constructors.For example,datatype color = red|blue|green;datatype color = blue | green | redPattern matching works on user-defined types using theirconstructors:fun translate red = "rot" | translate blue = "blau" | translate green = "gruen";val translate = fn : color -> string293CS 538 Spring 2006©fun jumble red = blue | jumble blue = green | jumble green = red;val jumble = fn : color -> colortranslate (jumble green);val it = "rot" : stringSML ExamplesSource code for most of the SMLexamples presented here may befound in~cs538-1/public/sml/class.sml294CS 538 Spring 2006©Parameterized ConstructorsThe constructors used to define datatypes may be parameterized:datatype money = none | coin of int | bill of int | iou of real * string;datatype money = bill of int | coin of int | iou of real * string | noneNow expressions like coin(25) orbill(5) or iou(10.25,"Lisa")represent valid values of type money.295CS 538 Spring 2006©We can also define values andfunctions of typemoney:val dime = coin(10);val dime = coin 10 : moneyval deadbeat =iou(25.00,"Homer Simpson");val deadbeat = iou (25.0,"Homer Simpson") : moneyfun amount(none) = 0.0 | amount(coin(cents)) = real(cents)/100.0 | amount(bill(dollars)) = real(dollars) | amount(iou(amt,_)) = 0.5*amt; val amount = fn : money -> real296CS 538 Spring 2006©Polymorphic DatatypesA user-defined data type may bepolymorphic. An excellent example isdatatype 'a option = none | some of 'a;datatype 'a option = none | some of 'aval zilch = none;val zilch = none : 'a optionval mucho =some(10e10);val mucho =some 100000000000.0 : real optiontype studentInfo = {name:string, ssNumber:int option};type studentInfo = {name:string,ssNumber:int option}297CS 538 Spring 2006©val newStudent ={name="Mystery Man", ssNumber=none}:studentInfo;val newStudent ={name="Mystery Man", ssNumber=none} : studentInfo298CS 538 Spring 2006©Datatypes may be RecursiveRecursive datatypes allow linkedstructures without explicit pointers.datatype binTree = null| leaf| node of binTree * binTree;datatype binTree =leaf | node of binTree * binTree | nullfun size(null) = 0 | size(leaf) = 1 | size(node(t1,t2)) = size(t1)+size(t2) + 1val size = fn : binTree -> int299CS 538 Spring 2006©Recursive Datatypes may


View Full Document

UW-Madison COMPSCI 538 - Lecture Notes

Download Lecture Notes
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Lecture Notes and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Lecture Notes 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?