Brief history of “programming” Al-Khwarizmi, 860AD

• “Programming” in the sense of devising rules , methods , procedures , recipes , algorithms , has always been present in human thought. • “Algorithm” originates from the name of Al-Khwarizmi, Arab mathematician from 800AD.

“Algorists” 1504AD Sumerian division algorithm, 2000BC

Sumerian division, translated Sumerian division, symbolically

[The number is 4;10. What is its inverse? The number is x. What is its inverse? Proceed as follows. Proceed as follows. Form the inverse of 10, you will find 6. Form the inverse of y, you will find y’ . Multiply 6 by 4, you will find 24. Multiply y’ by z. You will find t. Add on 1, you will find 25. Add on 1. You will find u. Form the inverse of 25], you will find 2;24. Form the inverse of u. You will find u’ . [Multiply 2;24 by 6], you will find 14;24. Multiply u’ by y’ . You will find v. [The inverse is 14;24]. Such is the way to proceed. The inverse is v. Such is the way to proceed.

1 Euclid’s algorithm for GCD Functional vs imperative

Proposition 2 Given two numbers not prime to one another, to find their greatest common • The Sumerian division algorithm, which is measure. representative of most algorithms in Mathematics, Let AB, CD be the two given numbers not prime to one another. is an example of a functional computation . Thus it is required to find the greatest common measure of AB, CD. • The Euclid’s GCD algorithm is an example of an ….. imperative computation, involving iteration and But, if CD does not measure AB, then the less of the numbers AB, CD, being state change. continually subtracted from the greater, some number will be left which will measure the one before it. • [For more details, see: Jean-Luc Chabert : A …Let such a number measure them, and let it be G. History of Algorithms , Springer, 1994] Now, since G measures CD, while CD measures BE, G also measures BE.

Functional computation Imperative computation

• Apply functions to input • Commands operate on the Store values or intermediate store , which contain values to compute new locations , and read or outputs. write them. • One view is: commands Commands • Type checking helps transform the state of the ensure the “plug- store ( i.e ., “functions” of compatibility” of the some sort). inputs/outputs. • Types are not of much help to ensure correctness.

Language Evolution Lisp Algol 60

Algol 68 Introduction to Haskell Pascal (Borrowed from Peyton Jones & John Mitchell) ML Modula C++

Haskell Java

Many others: Algol 58, Algol W, Scheme, EL1, Mesa (PARC), Modula-2, Oberon, Modula-3, Fortran, Ada, , Python, Ruby, C#, Javascript, F#…

2 C Programming Language ML programming language Dennis Ritchie, ACM Turing Award for Unix • Statically typed, general purpose systems programming • Statically typed, general-purpose programming language language – “Meta-Language” of the LCF theorem proving system • Computational model reflects underlying machine • Type safe, with formal semantics • Compiled language, but intended for interactive use • Relationship between arrays and pointers • Combination of Lisp and Algol-like features – An array is treated as a pointer to first element – Expression-oriented – E1[E2] is equivalent to ptr dereference: *((E1)+(E2)) – Higher-order functions – Pointer arithmetic is not common in other languages – Garbage collection • Not statically type safe – Abstract data types – Module system – If variable has type float, no guarantee value is floating pt – Exceptions • Ritchie quote • Used in printed textbook as example language – “C is quirky, flawed, and a tremendous success”

Robin Milner, ACM Turing-Award for ML, LCF Theorem Prover, …

Haskell Haskell B Curry • Haskell programming language is • Combinatory logic – Similar to ML: general-purpose, strongly typed, higher-order, – Influenced by Russell and Whitehead functional, supports type inference, interactive and compiled use – Developed combinators to represent – Different from ML: lazy evaluation, purely functional core, rapidly substitution – Alternate form of lambda calculus that evolving type system has been used in implementation structures • Designed by committee in 80’s and 90’s to unify research • Type inference efforts in lazy languages – Devised by Curry and Feys – Haskell 1.0 in 1990, Haskell ‘98, Haskell’ ongoing – Extended by Hindley, Milner – “A History of Haskell: Being Lazy with Class” HOPL 3

Although “Currying” and “Curried functions” Paul Hudak Simon are named after Curry, the idea was invented Peyton Jones by Schoenfinkel earlier

John Hughes Phil Wadler

Why Study Haskell? Why Study Haskell?

• Good vehicle for studying language concepts • Functional programming will make you think • Types and type checking differently about programming. – General issues in static and dynamic typing – Mainstream languages are all about state – Type inference – Functional programming is all about values – Parametric polymorphism • Haskell is “cutting edge” – Ad hoc polymorphism (aka, overloading) • Control – A lot of current research is done using Haskell – Rise of multi-core, parallel programming likely to – Lazy vs. eager evaluation make minimizing state much more important – Tail recursion and continuations – Precise management of effects • New ideas can help make you a better , in any language

3 Most Research Languages Successful Research Languages

1,000,000 1,000,000

10,000 10,000 Practitioners Practitioners

100 100 The slow death The quick death 1 1 Geeks Geeks

1yr 5yr 10yr 15yr 1yr 5yr 10yr 15yr

C++, Java, Perl, Ruby Committee languages Threshold of immortality 1,000,000 1,000,000

10,000 10,000 Practitioners The complete Practitioners 100 absence of death 100 The slow death

1 1 Geeks Geeks

1yr 5yr 10yr 15yr 1yr 5yr 10yr 15yr

“Learning Haskell is a great way of Haskell training yourself to think functionally so “I'm already looking at coding you are ready to take full advantage of problems and my mental C# 3.0 when it comes out” perspective is now shifting (blog Apr 2007) 1,000,000 back and forth between purely OO and more FP styled solutions” (blog Mar 2007) 10,000 Practitioners

100 The second life?

1 Geeks

1990 1995 2000 2005 2010

4 Function Types in Haskell Basic Overview of Haskell In Haskell, f :: A → B means for every x ∈ A, • Interactive (ghci): read-eval-print ∈ f(x) = some element y = f(x) B run forever – ghci infers type before compiling or executing – Type system does not allow casts or other loopholes! • Examples Prelude> (5+3)-2 In words, “if f(x) terminates, then f(x) ∈ B.” 6 it :: Integer Prelude> if 5>3 then “Harry” else “Hermione” In ML, functions with type A → B can throw an “Harry” exception or have other effects, but not in Haskell it :: [Char] -- String is equivalent to [Char] Prelude> 5==4 False it :: Bool

Overview by Type Simple Compound Types • Booleans True, False :: Bool  Tuples if … then … else … --types must match (4, 5, “Griffendor”) :: (Integer, Integer, String) • Integers  Lists 0, 1, 2, … :: Integer [] :: [a] -- polymorphic type +, * , … :: Integer -> Integer -> Integer 1 : [2, 3, 4] :: [Integer] -- infix cons notation • Strings “Ron Weasley”  Records  data Person = Person {firstName :: String, lastName :: String} • Floats hg = Person { firstName = “Hermione”, lastName = “Granger”} 1.0, 2, 3.14159, … --type classes to disambiguate

Haskell Libraries

Patterns and Declarations Functions and Pattern Matching • Patterns can be used in place of variables ::= | | | … • Function declaration form = • Value declarations  1 1 –General form: = = … –Examples = … myTuple = (“Flitwick”, “Snape”) • Examples (x,y) = myTuple myList = [1, 2, 3, 4] f (x,y) = x+y --argument must match pattern (x,y) length [] = 0 z:zs = myList length (x:s) = 1 + length(s) –Local declarations • let (x,y) = (2, “Snape”) in x * 4

5 More Functions on Lists More Efficient Reverse

reverse xs = • Append lists let rev ( [], accum ) = accum rev ( y:ys, accum ) = rev ( ys, y:accum ) append– ([], ys) = ys in rev ( xs, [] ) append– (x:xs, ys) = x : append (xs, ys) • Reverse a list – reverse [] = [] 1 3 reverse– (x:xs) = (reverse xs) ++ [x] • Questions 2 2 2 2 3 3 1 3 1 1 – How efficient is reverse? – Can it be done with only one pass through list?

List Comprehensions Datatype Declarations • Examples • Notation for constructing new lists from old: – data Color = Red | Yellow | Blue myData = [1,2,3,4,5,6,7] elements are Red, Yellow, Blue data Atom = Atom String | Number Int twiceData = [2 * x | x <- myData] -- [2,4,6,8,10,12,14] elements are Atom “A”, Atom “B”, …, Number 0, ... data List = Nil | Cons (Atom, List) twiceEvenData = [2 * x| x <- myData, x `mod` 2 == 0] -- [4,8,12] elements are Nil, Cons(Atom “A”, Nil), … Cons(Number 2, Cons(Atom(“Bill”), Nil)), ... • General form • Similar to “set comprehension” { x | x ∈ Odd ∧ x > 6 } – data = | … | ::= | – Type name and constructors must be Capitalized.

Datatypes and Pattern Matching Case Expression  Recursively defined data structure  Datatype data Tree = Leaf Int | Node (Int, Tree, Tree) data Exp = Var Int | Const Int | Plus (Exp, Exp)

4  Case expression Node(4, Node(3, Leaf 1, Leaf 2), Node(5, Leaf 6, Leaf 7)) case e of 3 5 Var n -> … Const n -> … Plus(e1,e2) -> … 1 2 6 7  Recursive function sum (Leaf n) = n sum (Node(n,t1,t2)) = n + sum(t1) + sum(t2) Indentation matters in case statements in Haskell.

6 Laziness Evaluation by Cases  Haskell is a lazy language data Exp = Var Int | Const Int | Plus (Exp, Exp)  Functions and data constructors don’t evaluate ev ( Var n) = Var n their arguments until they need them ev ( Const n ) = Const n ev ( Plus ( e1,e2 ) ) = cond :: Bool -> a -> a -> a case ev e1 of cond True t e = t cond False t e = e Var n -> Plus( Var n, ev e2) Const n -> case ev e2 of Var m -> Plus( Const n, Var m)  can write control-flow operators Const m -> Const (n+m) Plus(e3,e4) -> Plus ( Const n, that have to be built-in in eager languages Plus ( e3, e4 )) (||) :: Bool -> Bool -> Bool Plus(e3, e4) -> Plus( Plus ( e3, e4 ), ev e2) Short- circuiting True || x = True “or” False || x = x

Using Laziness A Lazy Paradigm isSubString :: String -> String -> Bool x `isSubString` s = or [ x `isPrefixOf` t | t <- suffixes s ] • Generate all solutions (an enormous tree) • Walk the tree to find the solution you want suffixes:: String -> [String] -- All suffixes of s type String = [Char] nextMove :: Board -> Move suffixes[] = [[]] nextMove b = selectMove allMoves suffixes(x:xs) = (x:xs) : suffixes xs where allMoves = allMovesFrom b or :: [Bool] -> Bool A gigantic (perhaps infinite) -- (or bs) returns True if any of the bs is True tree of possible moves or [] = False or (b:bs) = b || or bs

Core Haskell Testing • Basic Types – Unit • Patterns • It’s good to write tests as you write code – Booleans • Declarations • E.g. reverse undoes itself, etc. – Integers reverse xs = • Functions let rev ( [], zs ) = zs – Strings • Polymorphism rev ( y:ys, zs ) = rev( ys, y:zs ) – Reals in rev( xs, [] ) • Type declarations – Tuples -- Write properties in Haskell type TS = [Int] -- Test at this type – Lists • Type Classes – Records • Monads prop_RevRev :: TS -> Bool prop_RevRev ls = reverse (reverse ls) == ls • Exceptions

7 Test.QuickCheck is simply a Haskell Test Interactively (not a “tool”) QuickCheck

bash$ ghci intro.hs Prelude> :m +Test.QuickCheck • Generate random input based on type – Generators for values of type a has type Gen a Prelude Test.QuickCheck> quickCheck prop_RevRev – Have generators for many types +++ OK, passed 100 tests • Conditional properties – Have form ==> – Example: ordered xs = and (zipWith (<=) xs (drop 1 xs)) ...with a strange- insert x xs = takeWhile ( :t quickCheck ordered xs ==> ordered (insert x xs) quickCheck :: Testable prop => prop -> IO () where types = x::Int

Demo QuickCheck

QuickCheck Things to Notice • QuickCheck output No side effects. At all. – When property succeeds: quickCheck prop_RevRev OK, passed 100 tests. reverse:: [w] -> [w] – When a property fails, QuickCheck displays a counter-example. prop_RevId xs = reverse xs == xs where types = xs::[Int]  A call to reverse returns a new list; the old one quickCheck prop_RevId is unaffected. Falsifiable, after 1 tests: [-3,15] • Conditional testing prop_RevRev l = reverse(reverse l) == l – Discards test cases which do not satisfy the condition. – Test case generation continues until  A variable ‘l’ stands for an immutable value , • 100 cases which do satisfy the condition have been found, or not for a location whose value can change. • until an overall limit on the number of test cases is reached (to avoid looping if the condition never holds).  Laziness forces this purity. See : http://www.cse.chalmers.se/~rjmh/QuickCheck/manual.html

Things to Notice Things to Notice • Purity makes the interface explicit. • Pure functions are easy to test. reverse:: [w] -> [w] -- Haskell prop_RevRev l = reverse(reverse l) == l • Takes a list, and returns a list; that’s all. • In an imperative or OO language, you have to void reverse( list l ) /* C */ – set up the state of the object and the external state it reads or writes • Takes a list; may modify it; may modify – make the call other persistent state; may do I/O. – inspect the state of the object and the external state – perhaps copy part of the object or global state, so that you can use it in the post condition

8 Things to Notice More Info: haskell.org

Types are everywhere. • The Haskell wikibook reverse:: [w] -> [w] – http://en.wikibooks.org/wiki/Haskell • All the Haskell bloggers, sorted by topic • Usual static-typing panegyric omitted... – http://haskell.org/haskellwiki/Blog_articles • In Haskell, types express high-level design , in • Collected research papers about Haskell the same way that UML diagrams do, with – http://haskell.org/haskellwiki/Research_papers the advantage that the type signatures are • Wiki articles, by category machine-checked. – http://haskell.org/haskellwiki/Category:Haskell • Types are (almost always) optional: type • Books and tutorials inference fills them in if you leave them out. – http://haskell.org/haskellwiki/Books_and_tutorials

9