Introduction to ML - PowerPoint PPT Presentation

1 / 39
About This Presentation
Title:

Introduction to ML

Description:

take (x::xs, I) = if I 0 then x::take (xs, I - 1) else ... fun findroot (a, x, acc) = (* standard Newton ... fun incr x = x 1; val incr = fn : int - int ... – PowerPoint PPT presentation

Number of Views:57
Avg rating:3.0/5.0
Slides: 40
Provided by: Schon
Category:

less

Transcript and Presenter's Notes

Title: Introduction to ML


1
Introduction to ML
  • A Quasi-Functional Language
  • With Strong Typing
  • And Type Inference

2
Example of Interactive Session
  • Conventional syntax
  • val x 5 (user input )
  • val x 5 int (system
    response)
  • fun len lis if (null lis) then 0 else 1
    len (tl lis)
  • val len fn a list - int
  • Type inference for local entities
  • x x x
  • val it 125 int ( it denotes
    last computation)

3
Operations on lists
  • Similar to LISP, with (hd, tl, ) instead of
    (car, cdr, cons)
  • - fun append (x, y) if null (x)
    then y
  • else
    hd (x) append (tl (x), y)
  • val append fn a list a list -
    a list
  • ( a function that takes a pair of lists and
    yields a list )
  • - fun upto (m, n)
  • if m n then else m upto
    (m1, n)
  • val upto fn int int - int list
  • ( a function that takes two numbers and yields a
    list )

4
Patterns
  • A simple mechanism to describe and name parts of
    a structure fun prod 1 ( if list is
    empty )
  • prod (nns) n prod (ns) ( n is
    first element )
  • A list can be described by its head and its tail
  • fun maxl m int m
  • maxl (mnns) if m n then maxl (m
    ns)

  • else maxl (n ns)

5
Recursion and iteration
  • A function that returns the first i elements of a
    list
  • fun take ( , I)
  • take (xxs, I) if I 0 then
    xtake (xs, I - 1) else
  • Non-recursive version introduce an accumulator
    argument
  • fun itake ( , _, taken) taken (
    _ is pattern for anything )
  • itake (xxs, I, taken)
  • if I 0 then itake (xs, I -
    1, xtaken)
  • else taken
  • var rtake fn a list int a
    list - a list

6
A classic in functional form quicksort
  • fun quick
  • quick xreal x
  • quick (abs)
  • let fun partition (left, right, )
  • (quick
    left) _at_ (quick right)
  • partition (left, right,
    xxs)
  • if x (xleft, right, xs)
  • else
    partition (left, x right, xs)
  • in
  • partition (a, , bs)
    end
  • val quick fn real list - real list
  • note this assumes no repeating elements

7
A single formal is sufficient
  • If function takes more than one argument, say
    that it takes a single composite one
  • fun exp (x, n) if n 0 then 1
  • else x
    exp (x, n-1)
  • val exp fn int int - int
  • Single argument is a tuple (int, int)
  • Can also define records with named components

8
The type system
  • Primitive types bool, int, char, real, string
  • Constructors list, array, product (record),
    function
  • an expression has a corresponding type expression
  • the interpreter builds the type expression for
    each input
  • type checking requires that type expression of
    functions and their arguments match, and that
    type expression of context match result of
    function

9
Boolean Values
  • Two values
  • true and false
  • The usual set of logical operators etc

10
Integers (type int)
  • Can notate in either decimal or hex (0xaa)
  • Negative sign uses
  • This is because unary minus is an operator
  • But is part of the number
  • Most languages dont have negative literals
  • Which is an odd corner
  • All the usual arithmetic operators

11
Unsigned (type word)
  • A distinct type from int
  • Notated as 123w or 0wxff
  • Must be able to tell type of literal
  • From the literal itself
  • Without any context
  • Usual arithmetic operators
  • (but not abs, unary minus)

12
Floating-point Type (real)
  • Notated with either a decimal point and a
    fractional part or an exponent or both
  • 3.45
  • 3E4
  • Usual arithmetic operators
  • Note that usual arithmetic operators are
    overloaded, but must be able to tell type!
  • No implicit conversions between numeric types,
    functions in library used instead.

13
String Type
  • String is a primitive
  • Not a vector of characters
  • Usual notation (like Ada or C)
  • Carret () is concatenation
  • There is also a type char for single chars
  • Function str makes char into a string
  • Note everything is case sensitive
  • All keywords lower case

14
Example of Simple Arithmetic
  • Zeller function for day of the week
  • val floor Real.floorval real
    Real.fromIntval zc fn (d, m, y, c)
    (floor (2.61 real (m) - 0.2) d y y
    div 4 c div 4 - 2 c) mod 7
  • Note that the following are equivalent val zc
    fn fun zc

15
Local Variables
  • Zeller function rewritten (floor, real local)
  • local val floor Real.floor val real
    Real.fromIntin val zc fn (d, m, y, c)
    (floor (2.61 real (m) - 0.2) d y y
    div 4 c div 4 - 2 c) mod 7end

16
Use of let
  • Local allows decls used in other decls
  • Let allows decls used in expressions
  • ( Radix for non-negative nums ) val rec radix
    fn (n, base) let val b size base
    val digit fn n str (String.sub (base,
    n)) val radix' fn (true, n)
    digit n (false, n) radix (n div b,
    base) digit (n mod b) in radix' (n
    b, n) end

17
Block structure and nesting
  • Example of nesting
  • fun findroot (a, x, acc)
  • ( standard Newton-Raphson )
  • let val nextx (a / x x)
    / 2.0 (next approximation )
  • in
  • if abs (x - nextx) nextx

  • else findroot (a, nextx, acc)
  • end
  • (tail recursion rather than
    iteration )

18
What is an ML Program
  • So far we have seen functions and expressions,
    but what is an ML program?
  • Answer, a bunch of definitions and an expression
    to evaluate, typically
  • let declarations in expression
    end

19
Type inference
  • fun incr x x 1
  • val incr fn int - int
  • because of its appearance in (x1), x must be
    integer
  • fun add2 x incr (incr x)
  • val add2 fn int - int
  • incr returns an integer, so add2 does as well
  • x is argument of incr, so must be integer
  • val wrong 10.5 incr 7
  • Error operator and operand dont
    agree

20
Polymorphism
  • fun len x if null x then 0
  • else 1 len (tl x)
  • Works for any kind of list. What is its type
    expression?
  • val len fn a list - int
  • a denotes a type variable. Implicit universal
    quantification
  • for any a, len applies to a list of as.
  • fun copy lis if null lis then nil
  • else hd (lis)
    copy (tl lis)

21
Functionals
  • fun exists pred false
  • exists pred (xxs) (pred x) orelse
    exists pred xs
  • ( pred is a predicate a function that
    delivers a boolean )
  • val exists fn (a - bool) - a list
    - bool
  • fun all pred true
  • all pred (xxs) (pred x) andalso all
    pred xs val all fn (a - bool) - a
    list - bool
  • fun filter pred
  • filter (xxs)
  • if pred x then x filter pred xs
  • else filter pred xs
  • val filter fn (a - bool) - a list
    a list

22
Currying partial bindings
  • a b c means (a b) c (a b) yields a
    function that is applied to c
  • fun app2 x y if null x then y
  • else (hd x)
    app2 (tl x) y
  • val app2 fn a list - a list -
    a list
  • (a function that given a list yields a function
    that takes a list and yields a list )
  • val ap123 app2 1, 2, 3
  • val ap123 fn int list - int
    list
  • ap123 10, 20, 30
  • val it 1, 2, 3, 10, 20, 30

23
Type inference and unification
  • Type expressions are built by solving a set of
    equations
  • fun reduce f lis init if null lis
    then init
  • else f ((hd lis),
    reduce f (tl lis) init))
  • null a list - bool
  • hd b list - b
  • tl c list - c list
  • apply (d - e) d - e
    (function application)
  • let b be the type of init. Let a be the element
    type of lis.
  • Then f takes an a and a b and returns a b.
  • val reduce fn (a - b - b)
    - (a list) - b - b

24
Unification algorithm
  • A type variable can be unified with another
    variable
  • a unifies with b a and b are
    the same
  • A type variable can be unified with a constant
  • a unifies with int all occurences
    of a mean int
  • A type variable can be unified with an expression
  • a unifies with b list
  • a does not unify with a list
  • A constant can be unified with itself int is int
  • An expression can be unified with another
    expression if the constructors are identical and
    if the arguments can be unified (recursive)
  • (int - int) list unifies with a list, a is a
    function on integers

25
Type system does not handle overloading well
  • fun plus x y x y
  • operator is overloaded, cannot be resolved from
    context (error in some versions, defaults to int
    in others)
  • The type system can decide that a function takes
    a but not that it takes an int or real
  • Can use explicit typing to select interpretation
  • fun mix (x, y ,z) x y zreal
  • mix (real real real) - real

26
Parametric polymorphism vs. generics
  • A function whose type expression has type
    variables applies to an infinite set of types.
  • Equality of type expressions means structural
    equivalence.
  • All applications of a polymorphic function use
    the same body no need to instantiate.
  • let val ints 1, 2, 3
  • val strs this, that
  • in
  • len ints len strs ( int list -
    int, string list - int )
  • end
  • val it 5 int

27
User-defined types and inference
  • A user-defined type introduces constructors
  • datatype tree leaf of int node of tree
    tree
  • leaf and node are type constructors
  • can define functions by pattern
  • fun sum (leaf (t)) t
  • sum (node (t1, t2)) sum t1 sum
    t2
  • val sum fn tree - int

28
Parameterized datatypes
  • fun flatten (leaf (t)) t
  • flatten (node (t1, t2)) flatten (t1)
    _at_ flatten (t2)
  • flatten tree - int list
  • datatype a gentree leaf of a
  • node of a
    gentree a gentree
  • val names node (leaf (this), leaf
    (that))
  • Here names is of type string gentree

29
Programming in the large in ML
  • Need mechanisms for
  • Modularization
  • Information hiding
  • Parametrization of interfaces
  • While retaining type inference
  • Modules like packages / namespaces
  • Signatures like package specifications /Java
    interfaces
  • Functors like generics with formal packages

30
Structures
  • structure Complex
  • struct
  • type t real real
  • val zero (0.0, 0.0)t (qualification
    may be needed )
  • val i (0.0, 1.0)
  • fun sum ((x, y), (x1, y1)) (xx1,
    yy1)t
  • fun prod ((x, y), (x1, y1)) (xx1 yy1,
    xy1 yx1)t
  • fun inv ((x, y))
  • let val den xx yy
  • in
  • (x / den, y / den) t
  • end
  • fun quo (z, z1) prod (z, inv (z1))t
  • end

31
Using a structure
  • use (complex.ml)
  • signature Complex
  • Complex.prod (Complex.i, Complex.i)
  • val it (1.0, 0.0)
  • val pi4 (0.707, 0.707)
  • val pi4 real real structural
    equivalence
  • Complex.prod (pi4, pi4)
  • val it Complex.t

32
Signatures
  • Interface description without implementation
  • signature CMPLX
  • sig
  • type t
  • val zero t
  • val i t
  • val sum t t - t
  • val diff t t - t
  • val prod t t - t
  • val inv t - t
  • val quo t t - t
  • end

33
Multiple implementations
  • structure complex1 CMPLX
  • struct
  • type t realreal ( cartesian
    representation )
  • val zero (0.0, 0.0)
  • val i (0.0, 1.0)
  • Structure ComplexPolar CMPLX
  • Struct
  • type t realreal (polar
    representation)
  • val zero (0.0, 0.0)
  • val pi 3.141592
  • val i (0.0, pi / 2.0)

34
Information Hiding
  • Only signature should be visible
  • Declare structure to be opaque
  • structure polar CMPLX .
  • (Structure can be opaque or transparent depending
    on context).
  • Can export explicit constructors and equality for
    type. Otherwise, equivalent to limited private
    types in Ada.
  • Can declare as eqtype to export equality

35
Functors
  • Structures and signatures are not first-class
    objects.
  • A program (structure) can be parametrized by a
    signature
  • functor testComplex (C CMPLX)
  • struct
  • open C (equivalent
    to use clause)
  • fun FFT..
  • end
  • structure testPolar testComplex
    (Complexpolar)
  • ( equivalent to instantiation with a
    package )

36
Imperative Programming in ML
  • A real language needs operations with side
    effects, state, and variables
  • Need to retain type inference
  • - val p ref 5
  • val p ref 5 int ref ( ref is a
    type constructor)
  • - !p 2 (
    dereference operation )
  • val it 10 int
  • - p !p 3
  • val it ( ) unit (
    assignment has no value )
  • References are equality types (pointer equality)

37
The library
  • Lists structure useful Operations on Lists
  • Listpairs structure, operates on 2 lists,e.g.
  • ListPair.unzip ('a 'b) list - 'a list 'b
    list ListPair.zip 'a list 'b list - ('a
    'b) list
  • Vector operations (allow indexing)

38
Lazy Evaluation
  • Delay evaluation till value needed
  • Some languages do this by default (Haskel and
    Miranda are examples)
  • Advantage is avoiding evaluating stuff that is
    never needed, and aids correctness
  • fun take x y y
  • Are the following equivalent?
  • expr1
  • Take expr2 expr1
  • No, because expr2 might not terminate
  • ML is strict (but laziness can be simulated using
    functional forms that delay evaluation)
  • There are forms that assist in this approach
    (e.g. delayed)

39
Abstract Data Types
  • abstype 'a set null ins of 'a 'a setwith
    val emptyset null val addset ins fun
    memberset (x, null) false memberset (x,
    ins (v, s)) x v orelse memberset (x, s)
    local fun subset (null, _) true
    subset (ins (x, s1), s2)
    memberset (x, s1) andalso subset (s1, s2) in
    fun equalset (s1, s2) subset (s1, s2)
    andalso subset (s2, s1) end end
Write a Comment
User Comments (0)
About PowerShow.com