ML: a quasi-functional language with strong typing

Slides:



Advertisements
Similar presentations
Functional Programming Lecture 10 - type checking.
Advertisements

Programming with Lists
Modern Programming Languages, 2nd ed.
ML Lists.1 Standard ML Lists. ML Lists.2 Lists A list is a finite sequence of elements. [3,5,9] ["a", "list" ] [] Elements may appear more than once [3,4]
ML Lists.1 Standard ML Lists. ML Lists.2 Lists  A list is a finite sequence of elements. [3,5,9] ["a", "list" ] []  Elements may appear more than once.
A First Look at ML.
A Third Look At ML 1. Outline More pattern matching Function values and anonymous functions Higher-order functions and currying Predefined higher-order.
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists Dan Grossman Winter 2013.
ML Lists.1 Standard ML Lists. ML Lists.2 Lists  A list is a finite sequence of elements. [3,5,9] ["a", "list" ] []  ML lists are immutable.  Elements.
Cs776 (Prasad)L4Poly1 Polymorphic Type System. cs776 (Prasad)L4Poly2 Goals Allow expression of “for all types T” fun I x = x I : ’a -> ’a Allow expression.
ML Datatypes.1 Standard ML Data types. ML Datatypes.2 Concrete Datatypes  The datatype declaration creates new types  These are concrete data types,
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Chapter ElevenModern Programming Languages1 A Fourth Look At ML.
A First Look at ML Chapter FiveModern Programming Languages, 2nd ed.1.
Patterns in ML functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are the.
5/11/2015IT 3271 Types in ML (Ch 11) datatype bool = true | false; datatype 'element list = nil | :: of 'element * 'element list n Predefined, but not.
0 PROGRAMMING IN HASKELL Chapter 4 - Defining Functions.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site).
Introduction to ML - Part 2 Kenny Zhu. What is next? ML has a rich set of structured values Tuples: (17, true, “stuff”) Records: {name = “george”, age.
Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.
Introduction to ML A Quasi-Functional Language With Strong Typing And Type Inference.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
Type Checking  Legality checks  Operator determination  Overload resolution.
1 Functional Programming and ML. 2 What’s wrong with Imperative Languages? State State Introduces context sensitivity Introduces context sensitivity Harder.
Introduction to ML A Quasi-Functional Language With Strong Typing And Type Inference.
CS 2104 : Prog. Lang. Concepts. Functional Programming I Lecturer : Dr. Abhik Roychoudhury School of Computing From Dr. Khoo Siau Cheng’s lecture notes.
Introduction and Chapter 8 of Programming Languages by Ravi Sethi Elements of Functional Programming.
PrasadCS7761 Haskell Data Types/ADT/Modules Type/Class Hierarchy Lazy Functional Language.
Patterns in OCaml functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are.
Chapter 9: Functional Programming in a Typed Language.
A Second Look At ML 1. Outline Patterns Local variable definitions A sorting example 2.
A Third Look At ML Chapter NineModern Programming Languages, 2nd ed.1.
CS 2104 – Prog. Lang. Concepts Functional Programming II Lecturer : Dr. Abhik Roychoudhury School of Computing From Dr. Khoo Siau Cheng’s lecture notes.
1 CS 457/557: Functional Languages Lists and Algebraic Datatypes Mark P Jones Portland State University.
Error Example - 65/4; ! Toplevel input: ! 65/4; ! ^^ ! Type clash: expression of type ! int ! cannot have type ! real.
Chapter SevenModern Programming Languages1 A Second Look At ML.
A FIRST LOOK AT ML Chapter Five Modern Programming Languages 1.
ML Lists.1 Standard ML Lists. ML Lists.2 Lists  A list is a finite sequence of elements. [3,5,9] ["a", "list" ] []  Elements may appear more than once.
1 FP Foundations, Scheme In Text: Chapter Chapter 14: FP Foundations, Scheme Mathematical Functions Def: A mathematical function is a mapping of.
Type Checking and Type Inference
Principles of programming languages 12: Functional programming
CSE341: Programming Languages Lecture 7 First-Class Functions
Introduction to Scheme
ML Again ( Chapter 7) Patterns Local variable definitions
A lightening tour in 45 minutes
Objective caml Daniel Jackson MIT Lab for Computer Science 6898: Advanced Topics in Software Design March 18, 2002.
CSE341: Programming Languages Lecture 7 First-Class Functions
Nicholas Shahan Spring 2016
FP Foundations, Scheme In Text: Chapter 14.
Agenda SML Docs First-Class Functions Examples Standard Basis
Agenda SML Docs First-Class Functions Examples Standard Basis
CSE341: Programming Languages Lecture 7 First-Class Functions
Functions, Patterns and Datatypes
CSE 341 Section 5 Winter 2018.
Functions, Patterns and Datatypes
PROGRAMMING IN HASKELL
CSCE 314: Programming Languages Dr. Dylan Shell
Functions, Patterns and Datatypes
CSE-321 Programming Languages Introduction to Functional Programming
CSE341: Programming Languages Lecture 7 First-Class Functions
Announcements Quiz 5 HW6 due October 23
Functions, Patterns and Datatypes
CSE341: Programming Languages Lecture 7 First-Class Functions
CSE341: Programming Languages Lecture 7 First-Class Functions
Functions, Patterns and Datatypes
CSE341: Programming Languages Lecture 7 First-Class Functions
CSE341: Programming Languages Lecture 7 First-Class Functions
Presentation transcript:

ML: a quasi-functional language with strong typing 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 the last computation*)

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 (m+1, n); val upto = fn : int * int -> int list (*a function that takes two numbers and yields a list *)

Patterns A simple mechanism to describe and name parts of a structure: fun prod [ ] = 1 (* if list is empty *) | prod (n::ns) = n * prod (ns); (* n is first element *) A list can be described by its head and its tail fun maxl [m] : int = m | maxl (m::n::ns) if m > n then maxl (m ::ns) else maxl (n :: ns) > ** warning: patterns not exhaustive

Recursion and iteration A function that returns the first k elements of a list: fun take ([ ], k) = [ ] | take (x::xs, k) = if k > 0 then x::take (xs, k-1) else [ ]; Non-recursive version: introduce an accumulator argument: fun itake ([ ], _, taken) = taken (* _ is pattern for anything *) | itake (x::xs, k, taken) = if k > 0 then itake (xs, k-1, x::taken) else taken; > var itake = fn: ‘a list * int * ‘a list -> ‘a list

Block structure and nesting Let provides local scope: fun findroot (a, x, acc) = (* standard Newton-Raphson *) let val nextx = (a / x +x) / 2.0 (*next approximation *) in if abs (x - nextx) < acc*x then nextx else findroot (a, nextx, acc) end; (*tail recursion rather than iteration *)

A classic in functional form: quicksort fun quick [ ] = [ ] | quick [x:real] = [x] | quick (a::bs) = let fun partition (left, right [ ]) = (quick left) @ [a] @ (quick right) | partition (left, right, x::xs) = if x <= a then partition (x::left, right, xs) else partition (left, x:: right, xs) in partition ([ ], [ ], bs) end; > val quick : fn : real list -> real list;

Functionals fun exists pred [ ] = false | exists pred (x::xs) = (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 (x::xs) = (pred x) andalso all pred xs; fun filter pred [ ] = [ ] | filter (x::xs) = if pred x then x :: filter pred xs else filter pred xs; val filter = fn : (‘a -> bool) -> ‘a list –> ‘a list

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]

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) a product type Can also define records with named components

The type system Primitive types: 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 expressions of functions and their arguments match, and that type expression of context match result of function

Type inference - fun incr x = x + 1; val incr = fn : int -> int because of its appearance in (x+1), 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 don’t agree

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 a’s. - fun copy lis = if null lis then nil = else hd (lis) :: copy (tl lis);

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

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

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) Can use explicit typing to select interpretation: - fun mix (x, y ,z) = x * y + z:real; mix : (real * real * real) -> real

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 (as in Java) - 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

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 - fun flatten (leaf (t)) = [t] = | flatten (node (t1, t2)) = flatten (t1) @ flatten (t2); flatten: tree -> int list

Parameterized datatypes An idiom for containers: - datatype ‘a gentree = leaf of ‘a = | node of ‘a gentree * ‘a gentree; - val names = node (leaf (“this”), leaf (“that”)); val names = … string gentree More conventional: datatype ‘a gentree = nil | branch of ‘a * ‘a tree * ‘a tree

Functions on parametrized data types - fun mirror nil = nil = | mirror (branch (v, t1, t2)) = = branch (v, mirror t2, mirror t1)); val mirror = fn : ‘a gentree -> ‘a gentree - val trio = branch (“athos”, branch (“porthos”, nil, nil), branch (“aramis”, nil, nil)); val trio : string gentree

Pattern-matching on datatypes User-defined constructors work like list: leaf (a) matches a tree leaf, and bind a to the value of the leaf node (t1, t2) matches an internal node, and binds t1 and t2 to its two descendants Type declarations are structural: - type pair = int * int; - val thing = (666, 999); val thing: int * int