0% found this document useful (0 votes)
52 views

Brief History of "Programming"

The document provides a brief history of programming and algorithms from ancient times to modern functional programming languages like Haskell. It discusses early algorithms from Sumerian mathematics in 2000 BC and the work of Al-Khwarizmi in 800 AD that led to the term "algorithm". It then covers the evolution of programming languages from Lisp and Algol in the 1950s-60s to ML in the 1970s and Haskell in the 1990s. Haskell combined ideas from earlier functional languages with a pure focus on functions without side effects.
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
52 views

Brief History of "Programming"

The document provides a brief history of programming and algorithms from ancient times to modern functional programming languages like Haskell. It discusses early algorithms from Sumerian mathematics in 2000 BC and the work of Al-Khwarizmi in 800 AD that led to the term "algorithm". It then covers the evolution of programming languages from Lisp and Algol in the 1950s-60s to ML in the 1970s and Haskell in the 1990s. Haskell combined ideas from earlier functional languages with a pure focus on functions without side effects.
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 50

Brief history of “programming”

• “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.
Al-Khwarizmi, 860AD
“Algorists” 1504AD
Sumerian division algorithm,
2000BC
Sumerian division, translated
[The number is 4;10. What is its inverse?
Proceed as follows.
Form the inverse of 10, you will find 6.
Multiply 6 by 4, you will find 24.
Add on 1, you will find 25.
Form the inverse of 25], you will find 2;24.
[Multiply 2;24 by 6], you will find 14;24.
[The inverse is 14;24]. Such is the way to proceed.
Sumerian division, symbolically
The number is x. What is its inverse?
Proceed as follows.
Form the inverse of y, you will find y’.
Multiply y’ by z. You will find t.
Add on 1. You will find u.
Form the inverse of u. You will find u’ .
Multiply u’ by y’. You will find v.
The inverse is v. Such is the way to proceed.
Euclid’s algorithm for GCD
Proposition 2
Given two numbers not prime to one another, to find their greatest common
measure.
Let AB, CD be the two given numbers not prime to one another.
Thus it is required to find the greatest common measure of AB, CD.
…..
But, if CD does not measure AB, then the less of the numbers AB, CD, being
continually subtracted from the greater, some number will be left which will
measure the one before it.
…Let such a number measure them, and let it be G.
Now, since G measures CD, while CD measures BE, G also measures BE.
Functional vs imperative
• The Sumerian division algorithm, which is
representative of most algorithms in Mathematics,
is an example of a functional computation.
• The Euclid’s GCD algorithm is an example of an
imperative computation, involving iteration and
state change.
• [For more details, see: Jean-Luc Chabert: A
History of Algorithms, Springer, 1994]
Functional computation
• Apply functions to input
values or intermediate
values to compute new
outputs.
• Type checking helps
ensure the “plug-
compatibility” of the
inputs/outputs.
Imperative computation
• Commands operate on the
store, which contain Store
locations, and read or
write them.
• One view is: commands Commands
transform the state of the
store (i.e., “functions” of
some sort).
• Types are not of much
help to ensure correctness.
Introduction to Haskell

(Borrowed from
Peyton Jones & John Mitchell)
Language Evolution
Lisp
Algol 60

Algol 68

Pascal C
Smalltalk

ML Modula C++

Haskell Java
Many others: Algol 58, Algol W, Scheme, EL1, Mesa (PARC), Modula-2,
Oberon, Modula-3, Fortran, Ada, Perl, Python, Ruby, C#, Javascript, F#…
C Programming Language
Dennis Ritchie, ACM Turing Award for Unix

• Statically typed, general purpose systems programming


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

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


Haskell
• Haskell programming language is
– Similar to ML: general-purpose, strongly typed, higher-order,
functional, supports type inference, interactive and compiled use
– Different from ML: lazy evaluation, purely functional core,
rapidly evolving type system
• Designed by committee in 80’s and 90’s to unify research
efforts in lazy languages
– Haskell 1.0 in 1990, Haskell ‘98, Haskell’ ongoing
– “A History of Haskell: Being Lazy with Class” HOPL 3

Paul Hudak Simon Peyton


Jones

John Hughes Phil Wadler


Haskell B Curry
• Combinatory logic
– Influenced by Russell and Whitehead
– Developed combinators to represent
substitution
– Alternate form of lambda calculus that has
been used in implementation structures
• Type inference
– Devised by Curry and Feys
– Extended by Hindley, Milner

Although “Currying” and “Curried functions” are


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

1,000,000

10,000

100
Geeks

The quick death


1

1yr 5yr 10yr 15yr


Successful Research Languages
Practitioners

1,000,000

10,000

100
The slow death
Geeks

1yr 5yr 10yr 15yr


C++, Java, Perl, Ruby
Threshold of immortality
Practitioners

1,000,000

10,000
The complete
100 absence of death
Geeks

1yr 5yr 10yr 15yr


Committee languages
Practitioners

1,000,000

10,000

100
The slow death
Geeks

1yr 5yr 10yr 15yr


Haskell “Learning Haskell is a great way of
training yourself to think functionally so
you are ready to take full advantage of C#
“I'm already looking at coding 3.0 when it comes out”
Practitioners

problems and my mental (blog Apr 2007)


1,000,000 perspective is now shifting back
and forth between purely OO
and more FP styled solutions”
(blog Mar 2007)
10,000

100
The second life?
Geeks

1990 1995 2000 2005 2010


Function Types in Haskell
In Haskell, f :: A  B means for every x  A,

f(x) = some element y = f(x)  B


run forever

In words, “if f(x) terminates, then f(x)  B.”


In ML, functions with type A  B can throw an
exception or have other effects, but not in Haskell
Basic Overview of Haskell

• Interactive Interpreter (ghci): read-eval-print


– ghci infers type before compiling or executing
– Type system does not allow casts or other loopholes!
• Examples
Prelude> (5+3)-2
6
it :: Integer
Prelude> if 5>3 then “Harry” else “Hermione”
“Harry”
it :: [Char] -- String is equivalent to [Char]
Prelude> 5==4
False
it :: Bool
Overview by Type
• Booleans
True, False :: Bool
if … then … else … --types must match
• Integers
0, 1, 2, … :: Integer
+, * , … :: Integer -> Integer -> Integer

• Strings
“Ron Weasley”

• Floats
1.0, 2, 3.14159, … --type classes to disambiguate

Haskell Libraries
Simple Compound Types
 Tuples
(4, 5, “Griffendor”) :: (Integer, Integer, String)

 Lists
[] :: [a] -- polymorphic type

1 : [2, 3, 4] :: [Integer] -- infix cons notation

 Records
data Person = Person {firstName :: String,
lastName :: String}
hg = Person { firstName = “Hermione”,
lastName = “Granger”}
Patterns and Declarations
• Patterns can be used in place of variables
<pat> ::= <var> | <tuple> | <cons> | <record> …
• Value declarations
–General form: <pat> = <exp>
–Examples
myTuple = (“Flitwick”, “Snape”)
(x,y) = myTuple
myList = [1, 2, 3, 4]
z:zs = myList
–Local declarations

let (x,y) = (2, “Snape”) in x * 4
Functions and Pattern Matching
• Function declaration form
<name>
 <pat1> = <exp1>
<name> <pat2> = <exp2> …
<name> <patn> = <expn> …
• Examples

f (x,y) = x+y --argument must match pattern (x,y)
length [] = 0
length (x:s) = 1 + length(s)
More Functions on Lists
• Append lists

append ([], ys) = ys
append
– (x:xs, ys) = x : append (xs, ys)

• Reverse a list

reverse [] = []

reverse (x:xs) = (reverse xs) ++ [x]

• Questions
– How efficient is reverse?
– Can it be done with only one pass through list?
More Efficient Reverse
reverse xs =
let rev ( [], accum ) = accum
rev ( y:ys, accum ) = rev ( ys, y:accum )
in rev ( xs, [] )

1 3

2 2 2 2

3 3 1 3 1 1
List Comprehensions
• Notation for constructing new lists from old:
myData = [1,2,3,4,5,6,7]

twiceData = [2 * x | x <- myData]


-- [2,4,6,8,10,12,14]

twiceEvenData = [2 * x| x <- myData, x `mod` 2 == 0]


-- [4,8,12]

• Similar to “set comprehension”


{ x | x  Odd  x > 6 }
Datatype Declarations
• Examples
– data Color = Red | Yellow | Blue
elements are Red, Yellow, Blue
data Atom = Atom String | Number Int
elements are Atom “A”, Atom “B”, …, Number 0, ...
data List = Nil | Cons (Atom, List)
elements are Nil, Cons(Atom “A”, Nil), …
Cons(Number 2, Cons(Atom(“Bill”), Nil)), ...
• General form
– data <name> = <clause> | … | <clause>
<clause> ::= <constructor> | <contructor> <type>

– Type name and constructors must be Capitalized.


Datatypes and Pattern Matching
 Recursively defined data structure
data Tree = Leaf Int | Node (Int, Tree, Tree)

4
Node(4, Node(3, Leaf 1, Leaf 2),
Node(5, Leaf 6, Leaf 7))
3 5

1 2 6 7
 Recursive function
sum (Leaf n) = n
sum (Node(n,t1,t2)) = n + sum(t1) + sum(t2)
Case Expression
 Datatype
data Exp = Var Int | Const Int | Plus (Exp, Exp)

 Case expression
case e of
Var n -> …
Const n -> …
Plus(e1,e2) -> …

Indentation matters in case statements in Haskell.


Evaluation by Cases
data Exp = Var Int | Const Int | Plus (Exp, Exp)

ev ( Var n) = Var n
ev ( Const n ) = Const n
ev ( Plus ( e1,e2 ) ) =
case ev e1 of
Var n -> Plus( Var n, ev e2)
Const n -> case ev e2 of
Var m -> Plus( Const n, Var m)
Const m -> Const (n+m)

Plus(e3,e4) -> Plus ( Const n,


Plus ( e3, e4 ))

Plus(e3, e4) -> Plus( Plus ( e3, e4 ), ev e2)


Laziness
 Haskell is a lazy language
 Functions and data constructors don’t evaluate
their arguments until they need them
cond :: Bool -> a -> a -> a
cond True t e = t
cond False t e = e

 Programmers can write control-flow operators


that have to be built-in in eager languages
Short- (||) :: Bool -> Bool -> Bool
circuiting True || x = True
“or” False || x = x
Using Laziness
isSubString :: String -> String -> Bool
x `isSubString` s = or [ x `isPrefixOf` t
| t <- suffixes s ]

suffixes:: String -> [String]


type String = [Char]
-- All suffixes of s
suffixes[] = [[]]
suffixes(x:xs) = (x:xs) : suffixes xs

or :: [Bool] -> Bool


-- (or bs) returns True if any of the bs is True
or [] = False
or (b:bs) = b || or bs
A Lazy Paradigm
• Generate all solutions (an enormous tree)
• Walk the tree to find the solution you want
nextMove :: Board -> Move
nextMove b = selectMove allMoves
where
allMoves = allMovesFrom b

A gigantic (perhaps infinite)


tree of possible moves
Core Haskell
• Basic Types
– Unit • Patterns
– Booleans • Declarations
– Integers • Functions
– Strings • Polymorphism
– Reals
• Type declarations
– Tuples
– Lists
• Type Classes
– Records • Monads
• Exceptions
Testing
• It’s good to write tests as you write code
• E.g. reverse undoes itself, etc.
reverse xs =
let rev ( [], zs ) = zs
rev ( y:ys, zs ) = rev( ys, y:zs )
in rev( xs, [] )

-- Write properties in Haskell


type TS = [Int] -- Test at this type

prop_RevRev :: TS -> Bool


prop_RevRev ls = reverse (reverse ls) == ls
Test.QuickCheck is
simply a Haskell library
Test Interactively (not a “tool”)

bash$ ghci intro.hs


Prelude> :m +Test.QuickCheck

Prelude Test.QuickCheck> quickCheck prop_RevRev


+++ OK, passed 100 tests

...with a strange-looking
type

Prelude Test.QuickCheck> :t quickCheck


quickCheck :: Testable prop => prop -> IO ()

Demo QuickCheck
QuickCheck
• Generate random input based on type
– Generators for values of type a has type Gen a
– Have generators for many types
• Conditional properties
– Have form <condition> ==> <property>
– Example:
ordered xs = and (zipWith (<=) xs (drop 1 xs))
insert x xs = takeWhile (<x) xs++[x]++dropWhile (<x) xs
prop_Insert x xs =
ordered xs ==> ordered (insert x xs)
where types = x::Int
QuickCheck
• QuickCheck output
– When property succeeds:
quickCheck prop_RevRev OK, passed 100 tests.
– When a property fails, QuickCheck displays a counter-example.
prop_RevId xs = reverse xs == xs where types = xs::[Int]
quickCheck prop_RevId
Falsifiable, after 1 tests: [-3,15]
• Conditional testing
– Discards test cases which do not satisfy the condition.
– Test case generation continues until
• 100 cases which do satisfy the condition have been found, or
• until an overall limit on the number of test cases is reached (to
avoid looping if the condition never holds).
See : http://www.cse.chalmers.se/~rjmh/QuickCheck/manual.html
Things to Notice
No side effects. At all.
reverse:: [w] -> [w]

 A call to reverse returns a new list; the old one


is unaffected.
prop_RevRev l = reverse(reverse l) == l

 A variable ‘l’ stands for an immutable value,


not for a location whose value can change.
 Laziness forces this purity.
Things to Notice
• Purity makes the interface explicit.
reverse:: [w] -> [w] -- Haskell

• Takes a list, and returns a list; that’s all.


void reverse( list l ) /* C */

• Takes a list; may modify it; may modify


other persistent state; may do I/O.
Things to Notice
• Pure functions are easy to test.
prop_RevRev l = reverse(reverse l) == l

• In an imperative or OO language, you have to


– set up the state of the object and the external state it
reads or writes
– make the call
– 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
Things to Notice
Types are everywhere.
reverse:: [w] -> [w]

• Usual static-typing panegyric omitted...


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

You might also like