(* Lecture 8. Finite trees and datatypes *) (* Anyone could learn Lisp in one day, except that if they already knew Fortran,it would take three days. -Marvin Minsky *) (* Most large computer programs are never completely understood; if they were they wouldn't go wrong so often and we would be able to describe what they do in a scientific way. A good language should help to improve this state of affairs. There are many ways of trying to understand programs. People often rely too much on one way, which is called "debugging" and consists of running a partly-understood program to see if it does what you expected. Another way, which ML advocates, is to install some means of understanding in the very programs themselves. -Robin Milner *) (* quick revision of previous lecture *) (* factorial using the option datatype *) fun optFact n = case Int.compare(n,0) of GREATER => SOME(n * valOf(optFact(n-1))) | EQUAL => SOME 1 | LESS => NONE; (* Make a histogram (3-tupple) of numbers that are less, equal and greater than 0 from the list argument *) fun countLEG [] = (0,0,0) | countLEG (x::xs) = let val (y1,y2,y3) = countLEG xs in case Int.compare(x,0) of LESS => (y1+1, y2, y3) | EQUAL => (y1, y2+1, y3) | GREATER => (y1, y2, y3+1) end; countLEG [~3, ~2, 1, 2, 3, 0, 0]; (* Trees of ancestors A person's tree of ancestors contains information about her/his name together with the tree of the person's mother and father - or the tree of a person maybe unspecified. *) datatype ancTree = Unspec | Info of string * ancTree * ancTree; (* Info(n,mt,ft) name, mother's tree, father's tree *) val mom = Info("Anna", Info("Flora", Unspec, Unspec), Info("Elias", Unspec,Unspec)); val dad = Info("Panos", Info("Elli", Unspec, Unspec), Info("Giorgos", Unspec, Unspec)); val mytree = Info("Giorgos", mom, dad); (* pre-order traversal *) fun preorder Unspec = [] | preorder (Info(n,mt,ft)) = n::(preorder mt) @ (preorder ft); fun inorder Unspec = [] | inorder (Info(n,mt,ft)) = inorder(mt) @ [n] @ (inorder ft); fun postorder Unspec = [] | postorder (Info(n,mt,ft)) = postorder(mt) @ (postorder ft) @ [n]; (* return post-order list of female ancestors *) fun femanc Unspec = [] | femanc (Info(_,mt,ft)) = (femanc mt) @ (femanc ft) @ (case mt of Unspec => [] | Info(n,_,_) => [n]); (* filesystem datatype: list of files or directories where a directory contains a list of files or directories etc *) (* mutual recursive datatype *) datatype fselem = File of string | Directory of string * contents withtype contents = fselem list; val fs = Directory("d1", [File "f1", Directory("d2", [File "f2", Directory("d3", [File "f3"])]), File "f4", Directory("d4", [File "f5"])]); fun nameElem(File s) = [s] | nameElem(Directory(s,cnt)) = s::(nameContents cnt) and nameContents [] = [] | nameContents (e::es) = nameElem e @ (nameContents es); (* Electrical circuits *) datatype 'a circuit = Comp of 'a | Ser of 'a circuit * 'a circuit | Par of 'a circuit * 'a circuit; fun count (Comp _) = 1 | count (Ser(c1,c2)) = count c1 + count c2 | count (Par(c1,c2)) = count c1 + count c2 val mycirc = Ser(Par(Comp 0.25, Comp 1.0), Comp 1.5); val mycirc2 = Ser(Par(Comp "r1", Comp "r2"), Comp "r3"); fun resistance (Comp r) = r | resistance (Ser(c1,c2)) = resistance(c1) + resistance (c2) | resistance (Par(c1,c2)) = 1.0 / (1.0 / resistance(c1) + 1.0 / resistance(c2));