SML. CSE 307 Principles of Programming Languages Stony Brook University

Similar documents
Functional Programming

A First Look at ML. Chapter Five Modern Programming Languages, 2nd ed. 1

Mini-ML. CS 502 Lecture 2 8/28/08

Processadors de Llenguatge II. Functional Paradigm. Pratt A.7 Robert Harper s SML tutorial (Sec II)

SML A F unctional Functional Language Language Lecture 19

A Brief Introduction to Standard ML

Chapter 3 Linear Structures: Lists

Chapter 3 Linear Structures: Lists

Lists. Michael P. Fourman. February 2, 2010

Introduction to SML Basic Types, Tuples, Lists, Trees and Higher-Order Functions

Homework 3 COSE212, Fall 2018

CS109A ML Notes for the Week of 1/16/96. Using ML. ML can be used as an interactive language. We. shall use a version running under UNIX, called

Note that pcall can be implemented using futures. That is, instead of. we can use

Specification and Verification in Higher Order Logic

Redefinition of an identifier is OK, but this is redefinition not assignment; Thus

The type checker will complain that the two branches have different types, one is string and the other is int

Introduction to OCaml

A quick introduction to SML

If we have a call. Now consider fastmap, a version of map that uses futures: Now look at the call. That is, instead of

CSCI-GA Scripting Languages

CSE 341 Section 5. Winter 2018

Online Resource. Online introductory book on programming in SML (Standard ML): online.pdf

F28PL1 Programming Languages. Lecture 11: Standard ML 1

9/23/2014. Function: it s easy and it is fun Local Function & Composite Function Polymorphic function I/O Structure and signature

A Third Look At ML. Chapter Nine Modern Programming Languages, 2nd ed. 1

CSE341 Section 3. Standard-Library Docs, First-Class Functions, & More

CSE 505. Lecture #9. October 1, Lambda Calculus. Recursion and Fixed-points. Typed Lambda Calculi. Least Fixed Point

Lecture 2: The Basis of SML

A list is a finite sequence of elements. Elements may appear more than once

CSC324- TUTORIAL 5. Shems Saleh* *Some slides inspired by/based on Afsaneh Fazly s slides

COSE212: Programming Languages. Lecture 3 Functional Programming in OCaml

Introduction to SML Getting Started

Functional programming Primer I

Haskell 98 in short! CPSC 449 Principles of Programming Languages

Standard ML. Data types. ML Datatypes.1

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

Introduction to ML. Mooly Sagiv. Cornell CS 3110 Data Structures and Functional Programming

Functional Programming in Haskell Part I : Basics

All the operations used in the expression are over integers. a takes a pair as argument. (a pair is also a tuple, or more specifically, a 2-tuple)

9/19/12. Why Study Discrete Math? What is discrete? Sets (Rosen, Chapter 2) can be described by discrete math TOPICS

It is better to have 100 functions operate one one data structure, than 10 functions on 10 data structures. A. Perlis

A general introduction to Functional Programming using Haskell

02157 Functional Programming Lecture 2: Functions, Basic Types and Tuples

A Second Look At ML. Chapter Seven Modern Programming Languages, 2nd ed. 1

Functional Programming

Introduction to ML. Mooly Sagiv. Cornell CS 3110 Data Structures and Functional Programming

Announcements. CSCI 334: Principles of Programming Languages. Lecture 5: Fundamentals III & ML

OCaml. ML Flow. Complex types: Lists. Complex types: Lists. The PL for the discerning hacker. All elements must have same type.

LECTURE 16. Functional Programming

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Winter 2013

Datatype declarations

CSE 3302 Programming Languages Lecture 8: Functional Programming

Currying fun f x y = expression;

Plan (next 4 weeks) 1. Fast forward. 2. Rewind. 3. Slow motion. Rapid introduction to what s in OCaml. Go over the pieces individually

Fall Lecture 3 September 4. Stephen Brookes

Functional Programming

Lists. Adrian Groza. Department of Computer Science Technical University of Cluj-Napoca

Exercises on ML. Programming Languages. Chanseok Oh

Chapter 2 SML, a Functional Programming Language

2.1. Expressions. Chapter 2 SML, a Functional Programming Language. Integers. Interacting with ML

Type Checking and Type Inference

Functors signature Order = sig functor name type elem (structname:signature) = structure definition; val le : elem*elem -> bool end; elem

Haskell through HUGS THE BASICS

Functional Programming. Pure Functional Programming

CSCC24 Functional Programming Typing, Scope, Exceptions ML

Recursion. Lars-Henrik Eriksson. Functional Programming 1. Based on a presentation by Tjark Weber and notes by Sven-Olof Nyström

Inductive Data Types

General Computer Science (CH ) Fall 2016 SML Tutorial: Practice Problems

cs242 Kathleen Fisher Reading: Concepts in Programming Languages, Chapter 6 Thanks to John Mitchell for some of these slides.

Handout 2 August 25, 2008

Scheme Quick Reference

Scheme Quick Reference

Introduction to ML. Mooly Sagiv. Cornell CS 3110 Data Structures and Functional Programming

List Processing in SML

Haskell 5.1 INTERACTIVE SESSIONS AND THE RUN-TIME SYSTEM

CSE341, Fall 2011, Midterm Examination October 31, 2011

An informal tutorial on Joy 1

CSC312 Principles of Programming Languages : Functional Programming Language. Copyright 2006 The McGraw-Hill Companies, Inc.

Types, Type Inference and Unification

CSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer Science (Arkoudas and Musser) Chapter p. 1/27

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Fall 2011

02157 Functional Programming Lecture 1: Introduction and Getting Started

Programming Paradigms Languages F28PL, Lecture 1

Delayed Expressions Fall 2017 Discussion 9: November 8, Iterables and Iterators. For Loops. Other Iterable Uses

CSE-321 Programming Languages 2012 Midterm

[Ch 6] Set Theory. 1. Basic Concepts and Definitions. 400 lecture note #4. 1) Basics

Overloading, Type Classes, and Algebraic Datatypes

n n Try tutorial on front page to get started! n spring13/ n Stack Overflow!

Principles of Programming Languages COMP3031: Functional Programming in SML

Products and Records

List Processing in SML

Begin at the beginning

2.1. Expressions. Chapter 2 ML, a Functional Programming Language. Integers. Interacting with ML

Recursion defining an object (or function, algorithm, etc.) in terms of itself. Recursion can be used to define sequences

Principles of Programming Languages

OCaml. History, Variants. ML s holy trinity. Interacting with ML. Base type: Integers. Base type: Strings. *Notes from Sorin Lerner at UCSD*

CSc 372 Comparative Programming Languages

Lambda Calculus as a Programming Language

CSci 4223 Principles of Programming Languages

Types and Programming Languages. Lecture 5. Extensions of simple types

Transcription:

SML CSE 307 Principles of Programming Languages Stony Brook University http://www.cs.stonybrook.edu/~cse307 1

Functional Programming Function evaluation is the basic concept for a programming paradigm that has been implemented in functional programming languages. 2 The language ML ( Meta Language ) was originally introduced in the 1970 s as part of a theorem proving system, and was intended for describing and implementing proof strategies in the Logic for Computable Functions (LCF) theorem prover (whose language, pplambda, a combination of the first-order predicate calculus and the simply typed polymorphic lambda calculus, had ML as its metalanguage) Standard ML of New Jersey (SML) is an implementation of ML. The basic mode of computation in SML is the use of the definition and application of functions.

Install Standard ML Download from: http://www.smlnj.org Start Standard ML: Type sml from the shell (run command line in Windows) Exit Standard ML: Ctrl-Z under Windows Ctrl-D under Unix/Mac 3

Standard ML The basic cycle of SML activity has three parts: read input from the user, evaluate it, print the computed value (or an error message). 4

First SML example SML prompt: - Simple example: - 3; val it = 3 : int The first line contains the SML prompt, followed by an expression typed in by the user and ended by a semicolon. The second line is SML s response, indicating the value of the input expression and its type. 5

Interacting with SML SML has a number of built-in operators and data types. it provides the standard arithmetic operators 6-3+2; val it = 5 : int The Boolean values true and false are available, as are logical operators such as not (negation), andalso (conjunction), and orelse (disjunction). - not(true); val it = false : bool - true andalso false; val it = false : bool

Types in SML As part of the evaluation process, SML determines the type of the output value using methods of type inference. Simple types include int, real, bool, and string. One can also associate identifiers with values - val five = 3+2; val five = 5 : int and thereby establish a new value binding - five; val it = 5 : int 7

Function Definitions in SML The general form of a function definition in SML is: fun <identifier> (<parameters>) = <expression>; For example, 8 - fun double(x) = 2*x; val double = fn : int -> int declares double as a function from integers to integers, i.e., of type int int Apply a function to an argument of the wrong type results in an error message: - double(2.0); Error: operator and operand don t agree...

Function Definitions in SML The user may also explicitly indicate types: - fun max(x:int,y:int,z:int) = if ((x>y) andalso (x>z)) then x else (if (y>z) then y else z); val max = fn : int * int * int -> int - max(3,2,2); val it = 3 : int 9

Recursive Definitions The use of recursive definitions is a main characteristic of functional programming languages, and these languages encourage the use of recursion over iterative constructs such as while loops: - fun factorial(x) = if x=0 then 1 else x*factorial(x-1); val factorial = fn : int -> int The definition is used by SML to evaluate applications of the function to specific arguments. - factorial(5); val it = 120 : int - factorial(10); val it = 3628800 : int 10

Example: Greatest Common Divisor The greatest common divisor (gcd) of two positive integers can defined recursively based on the following observations: 1. gcd(n, n) = n, 2. gcd(m, n) = gcd(n,m), and 3. gcd(m, n) = gcd(m n, n), if m > n. These identities suggest the following recursive definition: - fun gcd(m,n):int = if m=n then n else if m>n then gcd(m-n,n) else gcd(m,n-m); val gcd = fn : int * int -> int - gcd(12,30); - gcd(1,20); - gcd(125,56345); val it = 6 : int val it = 1 : int val it = 5 : int 11

More recursive functions - fun exp(b,n) = if n=0 then 1.0 else b * exp(b,n-1); val exp = fn : real * int -> real - exp(2.0,10); val it = 1024.0 : real 12

Tuples in SML 13 In SML tuples are finite sequences of arbitrary but fixed length, where different components need not be of the same type. - (1, "two"); val it = (1,"two") : int * string - val t1 = (1,2,3); val t1 = (1,2,3) : int * int * int - val t2 = (4,(5.0,6)); val t2 = (4,(5.0,6)) : int * (real * int) The components of a tuple can be accessed by applying the built-in functions #i, where i is a positive number. - #1(t1); val it = 1 : int - #2(t2); val it = (5.0,6) : real * int If a function #i is applied to a tuple with fewer than i components, an error results.

Polymorphic functions - fun id x = x; val id = fn : 'a -> 'a - (id 1, id "two"); val it = (1,"two") : int * string - fun fst(x,y) = x; val fst = fn : 'a * 'b -> 'a - fun snd(x,y) = y; val snd = fn : 'a * 'b -> 'b - fun switch(x,y) = (y,x); val switch = fn : 'a * 'b -> 'b * 'a 14

Lists in SML A list in SML is a finite sequence of objects, all of the same type: - [1,2,3]; val it = [1,2,3] : int list - [true,false,true]; val it = [true,false,true] : bool list - [[1,2,3],[4,5],[6]]; val it = [[1,2,3],[4,5],[6]] : int list list The last example is a list of lists of integers. 15

Lists in SML All objects in a list must be of the same type: - [1,[2]]; Error: operator and operand don t agree An empty list is denoted by one of the following expressions: - []; val it = [] : a list - nil; val it = [] : a list Note that the type is described in terms of a type variable a. Instantiating the type variable, by types such as int, results in (different) empty lists of corresponding types. 16

Operations on Lists SML provides various functions for manipulating lists. The function hd returns the first element of its argument list. 17 - hd[1,2,3]; val it = 1 : int - hd[[1,2],[3]]; val it = [1,2] : int list Applying this function to the empty list will result in an error. The function tl removes the first element of its argument lists, and returns the remaining list. - tl[1,2,3]; val it = [2,3] : int list - tl[[1,2],[3]]; val it = [[3]] : int list list The application of this function to the empty list will also result in an error.

Operations on Lists Lists can be constructed by the (binary) function :: (read cons) that adds its first argument to the front of the second argument. - 5::[]; val it = [5] : int list - 1::[2,3]; val it = [1,2,3] : int list - [1,2]::[[3],[4,5,6,7]]; val it = [[1,2],[3],[4,5,6,7]] : int list list The arguments must be of the right type (such that the result is a list of elements of the same type): - [1]::[2,3]; Error: operator and operand don t agree 18

Operations on Lists Lists can also be compared for equality: - [1,2,3]=[1,2,3]; val it = true : bool - [1,2]=[2,1]; val it = false : bool - tl[1] = []; val it = true : bool 19

Defining List Functions Recursion is particularly useful for defining functions that process lists. For example, consider the problem of defining an SML function that takes as arguments two lists of the same type and returns the concatenated list. In defining such list functions, it is helpful to keep in mind that a list is either an empty list [] or of the form x::y 20

Concatenation 21 In designing a function for concatenating two lists x and y we thus distinguish two cases, depending on the form of x: If x is an empty list [], then concatenating x with y yields just y. If x is of the form x1::x2, then concatenating x with y is a list of the form x1::z, where z is the result of concatenating x2 with y. We can be more specific by observing that x = hd(x)::tl(x)

Concatenation - fun concat(x,y) = if x=[] then y else hd(x)::concat(tl(x),y); val concat = fn : a list * a list -> a list Applying the function yields the expected results: - concat([1,2],[3,4,5]); val it = [1,2,3,4,5] : int list - concat([],[1,2]); val it = [1,2] : int list - concat([1,2],[]); val it = [1,2] : int list 22

Length The following function computes the length of its argument list: - fun length(l) = if (L=nil) then 0 else 1+length(tl(L)); val length = fn : a list -> int 23 - length[1,2,3]; val it = 3 : int - length[[5],[4],[3],[2,1]]; val it = 4 : int - length[]; val it = 0 : int

doubleall The following function doubles all the elements in its argument list (of integers): - fun doubleall(l) = if L=[] then [] else (2*hd(L))::doubleall(tl(L)); val doubleall = fn : int list -> int list - doubleall[1,3,5,7]; val it = [2,6,10,14] : int list 24

Reversing a List 25 Concatenation of lists, for which we gave a recursive definition, is actually a built-in operator in SML, denoted by the symbol @. We use this operator in the following recursive definition of a function that reverses a list. - fun reverse(l) = if L = nil then nil else reverse(tl(l)) @ [hd(l)]; val reverse = fn : a list -> a list - reverse [1,2,3]; val it = [3,2,1] : int list This method is not efficient: O(n 2 )

Reversing a List This way (using an accumulator) is better: O(n) - fun reverse_helper(l,l2) = if L = nil then L2 else reverse_helper(tl(l),hd(l)::l2); - fun reverse(l) = reverse_helper(l,[]); 26

Removing List Elements The following function removes all occurrences of its first argument from its second argument list. - fun remove(x,l) = if (L=[]) then [] else if x=hd(l)then remove(x,tl(l)) else hd(l)::remove(x,tl(l)); val remove = fn : a * a list -> a list - remove(1,[5,3,1]); val it = [5,3] : int list - remove(2,[4,2,4,2,4,2,2]); val it = [4,4,4] : int list 27

Removing Duplicates The remove function can be used in the definition of another function that removes all duplicate occurrences of elements from its argument list: - fun removedupl(l) = if (L=[]) then [] else hd(l)::removedupl(remove(hd(l),tl(l))); val removedupl = fn : a list -> a list - removedupl([3,2,4,6,4,3,2,3,4,3,2,1]); val it = [3,2,4,6,1] : int list 28

Definition by Patterns 29 In SML functions can also be defined via patterns. The general form of such definitions is: fun <identifier>(<pattern1>) = <expression1> <identifier>(<pattern2>) = <expression2>... <identifier>(<patternk>) = <expressionk>; where the identifiers, which name the function, are all the same, all patterns are of the same type, and all expressions are of the same type. Example: - fun reverse(nil) = nil The patterns are inspected in order and the first match determines the value of the function. reverse(x::xs) = reverse(xs) @ [x]; val reverse = fn : a list -> a list

Sets with lists in SML fun member(x,l) = if L=[] then false else if X=hd(L) then true else member(x,tl(l)); OR with patterns: fun member(x,[]) = false member(x,y::ys) = if (X=Y) then true else member(x,ys); member(1,[1,2]); (* true *) member(1,[2,1]); (* true *) member(1,[2,3]); (* false *) 30

fun union(l1,l2) = if L1=[] then L2 else if member(hd(l1),l2) then union(tl(l1),l2) else hd(l1)::union(tl(l1),l2); union([1,5,7,9],[2,3,5,10]); (* [1,7,9,2,3,5,10] *) union([],[1,2]); (* [1,2] *) union([1,2],[]); (* [1,2] *) 31 Sets - UNION

Sets - UNION patterns fun union([],l2) = L2 union(x::xs,l2) = if member(x,l2) then union(xs,l2) else X::union(Xs,L2); union([1,5,7,9],[2,3,5,10]); (* [1,7,9,2,3,5,10] *) union([],[1,2]); (* [1,2] *) union([1,2],[]); (* [1,2] *) 32

Sets - Intersection fun intersection(l1,l2) = if L1=[] then [] else if member(hd(l1),l2) then hd(l1)::intersection(tl(l1),l2) else intersection(tl(l1),l2); intersection([1,5,7,9],[2,3,5,10]); (* [5] *) 33

Sets - patterns fun intersection([],l2) = [] intersection(l1,[]) = [] intersection(x::xs,l2) = if member(x,l2) then X::intersection(Xs,L2) else intersection(xs,l2); intersection([1,5,7,9],[2,3,5,10]); (* [5] *) 34

Sets subset fun subset(l1,l2) = if L1=[] then true else if L2=[] then false else if member(hd(l1),l2) then subset(tl(l1),l2) else false; subset([1,5,7,9],[2,3,5,10]); (* false *) subset([5],[2,3,5,10]); (* true *) 35

36 Sets subset patterns fun subset([],l2) = true subset(l1,[]) = if(l1=[]) then true else false subset(x::xs,l2) = if member(x,l2) then subset(xs,l2) else false; subset([1,5,7,9],[2,3,5,10]); (* false *) subset([5],[2,3,5,10]); (* true *)

Sets equals fun setequal(l1,l2) = subset(l1,l2) andalso subset(l2,l1); setequal([1,5,7],[7,5,1,2]); (* false *) setequal([1,5,7],[7,5,1]); (* true *) 37

Sets minus patterns fun minus([],l2) = [] minus(x::xs,l2) = if member(x,l2) then minus(xs,l2) else X::minus(Xs,L2); minus([1,5,7,9],[2,3,5,10]); (* [1,7,9] *) 38

39 Sets - Cartesian product fun product_one(x,[]) = [] product_one(x,y::ys) = (X,Y)::product_one(X,Ys); product_one(1,[2,3]); (* [(1,2),(1,3)] *) fun product([],l2) = [] product(x::xs,l2) = union(product_one(x,l2), product(xs,l2)); product([1,5,7,9],[2,3,5,10]); (* [(1,2),(1,3),(1,5),(1,10),(5,2), (5,3),(5,5),(5,10),(7,2),(7,3),...] *)

Sets Powerset fun insert_all(e,l) = if L=[] then [] else (E::hd(L)) :: insert_all(e,tl(l)); insert_all(1,[[],[2],[3],[2,3]]); (* [ [1], [1,2], [1,3], [1,2,3] ] *) fun powerset(l) = if L=[] then [[]] else powerset(tl(l)) @ insert_all(hd(l),powerset(tl(l))); 40 powerset([]); powerset([1,2,3]); powerset([2,3]);

Records Records are structured data types of heterogeneous elements that are labeled - {x=2, y=3}; The order does not matter: - {make="toyota", model="corolla", year=2017, color="silver"} = {model="corolla", make="toyota", color="silver", year=2017}; val it = true : bool - fun full_name{first:string,last:string, age:int,balance:real}:string = first ^ " " ^ last; (* ^ is the string concatenation operator *) val full_name=fn:{age:int, balance:real, first:string, last:string} -> string 41

User defined data types - datatype shape = Rectangle of real*real Circle of real Line of (real*real)list; datatype shape = Circle of real Line of (real * real) list Rectangle of real * real 42

Higher-Order Functions In functional programming languages functions can be used in definitions of other, so-called higher-order, functions. The following function, map, applies its first argument (a function) to all elements in its second argument (a list of suitable type): - fun map(f,l) = if (L=[]) then [] else f(hd(l))::(map(f,tl(l))); val map = fn : ( a -> b) * a list -> b list We may apply map with any function as argument: - fun square(x) = (x:int)*x; val square = fn : int -> int - map(square,[2,3,4]); val it = [4,9,16] : int list 43

Higher-Order Functions More map examples Anonymous functions: - map(fn x=>x+1, [1,2,3,4,5]); val it = [2,3,4,5,6] : int list - fun incr(list) = map (fn x=>x+1, list); val incr = fn : int list -> int list - incr[1,2,3,4,5]; val it = [2,3,4,5,6] : int list 44

McCarthy's 91 function McCarthy's 91 function: - fun mc91(n) = if n>100 then n-10 else mc91(mc91(n+11)); val mc91 = fn : int -> int - map mc91 [101, 100, 99, 98, 97, 96]; val it = [91,91,91,91,91,91] : int list 45

Filter Filter: keep in a list only the values that satisfy some logical condition/boolean function - fun filter(f,l) = if l=[] then [] else if f(hd l) then (hd l)::(filter (f, tl l)) else filter(f, tl l); val filter = fn : ('a -> bool) * 'a list -> 'a list - filter((fn x => x>0), [~1,0,1]); val it = [1] : int list 46

Permutations - fun myinterleave(x,[]) = [[x]] myinterleave(x,h::t) = (x::h::t)::( map((fn l => h::l), myinterleave(x,t))); - myinterleave(1,[]); val it = [[1]] : int list list - myinterleave(1,[2]); val it = [[1,2],[2,1]] : int list list - myinterleave(1,[2,3]); val it = [[1,2,3],[2,1,3],[2,3,1]] : int list list 47

Permutations - fun appendall(nil) = nil appendall(z::zs) = z @ (appendall(zs)); - appendall([[[1,2]],[[2,1]]]); val it = [[1,2],[2,1]] : int list list - fun permute(nil) = [[]] permute(h::t) = appendall( map((fn l => myinterleave(h,l)), permute(t))); - permute([1,2,3]); val it = [[1,2,3],[2,1,3],[2,3,1],[1,3,2],[3,1,2], [3,2,1]] : int list list 48

Currying - fun f(a)(b)(c) = a+b+c; val f = fn : int -> int -> int -> int val f = fn : int -> (int -> (int -> int)) OR - fun f a b c = a+b+c; - val inc1 = f(1); val inc1 = fn : int -> int -> int val inc1 = fn : int -> (int -> int) - val inc12 = inc1(2); val inc12 = fn : int -> int - inc12(3); val it = 6 : int 49

Composition Composition is another example of a higher-order function: - fun comp(f,g)(x) = f(g(x)); val comp = fn : ('a -> 'b) * ('c -> 'a) -> 'c -> 'b - val f = comp(math.sin, Math.cos); val f = fn : real -> real SAME WITH: - val g = Math.sin o Math.cos; (* Composition "o" is predefined *) val g = fn : real -> real - f(0.25); val it = 0.824270418114 : real - g(0.25); val it = 0.824270418114 : real 50

Mutually recursive function definitions - fun odd(n) = if n=0 then false and else even(n-1) even(n) = if n=0 then true else odd(n-1); val odd = fn : int -> bool val even = fn : int -> bool - even(1); val it = false : bool - odd(1); val it = true : bool 51

Sorting 52 We next design a function for sorting a list of integers: The function is recursive and based on a method known as Merge-Sort. To sort a list L: first split L into two disjoint sublists (of about equal size), then (recursively) sort the sublists, and finally merge the (now sorted) sublists. This recursive method is known as Merge-Sort It requires suitable functions for splitting a list into two sublists AND merging two sorted lists into one sorted list

Splitting 53 We split a list by applying two functions, take and skip, which extract alternate elements; respectively, the elements at odd-numbered positions and the elements at even-numbered positions (if any). The definitions of the two functions mutually depend on each other, and hence provide an example of mutual recursion, as indicated by the SML-keyword and: - fun take(l) = and skip(l) = if L = nil then nil else hd(l)::skip(tl(l)) if L=nil then nil else take(tl(l)); val take = fn : a list -> a list val skip = fn : a list -> a list - take[1,2,3,4,5,6,7]; val it = [1,3,5,7] : int list - skip[1,2,3,4,5,6,7]; val it = [2,4,6] : int list

Merging Merge pattern definition: - fun merge([],m) = M merge(l,[]) = L merge(x::xl,y::yl) = if (x:int)<y then x::merge(xl,y::yl) else y::merge(x::xl,yl); val merge = fn : int list * int list -> int list 54 - merge([1,5,7,9],[2,3,5,5,10]); val it = [1,2,3,5,5,5,7,9,10] : int list - merge([],[1,2]); val it = [1,2] : int list - merge([1,2],[]); val it = [1,2] : int list

Merge Sort - fun sort(l) = if L=[] then [] else merge(sort(take(l)),sort(skip(l))); val sort = fn : int list -> int list 55

string and char - "a"; val it = "a" : string - #"a"; val it = #"a" : char - explode("ab"); val it = [#"a",#"b"] : char list - implode([#"a",#"b"]); val it = "ab" : string - "abc" ^ "def" = "abcdef"; val it = true : bool - size ("abcd"); val it = 4 : int 56

string and char - String.sub("abcde",2); val it = #"c" : char - substring("abcdefghij",3,4); val it = "defg" : string - concat ["AB"," ","CD"]; val it = "AB CD" : string - str(#"x"); val it = "x" : string 57

The program of Young McML fun tartan_column(i,j,n) = if j=n+1 then "\n" else if (i+j) mod 2=1 then concat(["* ",tartan_column(i,j+1,n)]) else concat(["+ ",tartan_column(i,j+1,n)]); fun tartan_row(i,n) = if i=n+1 then "" else concat([tartan_column(i,1,n), tartan_row(i+1,n)]); fun tartan(n) = tartan_row(1,n); print(tartan(30)); 58