44
Logos Island Guru Bluff Bottomless Methodology Caves Cannibals Temple of the Zillionth Feature Performance Falls Nil Point Compiler Pass Ivory Towers Software Pirates Cove PhD Springs Mother Lode Binary Jungle Vast Typele ss Traps Co r a l R e f E l e c t r i c S ea Pointer F orest I m p e n etra ble I O S tre a m S li p pery S l o pes B u g gy Bi g h t B a y o f N a ï v e t é V a l le y Mo n o m o r p h ic Memory Leaks Consid erable Coast C r i t i c a l P a t h ++ Lazy Swamp O ptim iz at i o n Ra p i d s + + + + + + + L a p top B each + Doped Silicon Mines Inter m itte nt F a u lts D a taF l o w C o n t r o l F l o w + Opaque View C o d e W a lk Audit T rai l + Loophole Lair Brown-out C u rren t N LC 93 Z R Q + Scope Nest U s e r D e s e r t Great Ad-Hoc Volcano Abstraction Peaks

Introduction to Functional Languages

  • Upload
    suthi

  • View
    157

  • Download
    0

Embed Size (px)

Citation preview

Logos Island

GuruBluff

Bottomless Methodology

Caves

Cannibals

Temple of theZillionth Feature

PerformanceFalls

Nil Point

Compiler Pass

Ivory Towers

SoftwarePiratesCove

PhDSprings

Mother Lode

BinaryJungle

Vast Typeless TrapsCoral Ref

Electric Sea

Pointer ForestImpenetrable

IO Stream

Sli

ppery

Slopes

Bugg

yBi

ght

Bay of Naïveté

ValleyM

onomorphic

Memory Leaks

Considerable Coast

Criti

calP

ath

+ +

LazySwamp

OptimizationRapids

+

+

+

+ +

+

+

Laptop Beach

+DopedSiliconMines

Intermittent Faults

Data FlowControl Flow

+OpaqueView

Code

Wal

kAudit Trail

+LoopholeLair

Brown-out Current

N

LC93

Z

R Q

+ScopeNest

User

Desert

GreatAd-HocVolcano

AbstractionPeaks

Introduction to Functional Languages

1. Referential transparency, no side effects“substitution of equals for equals”

2. Function definitions can be usedSuppose f is defined to be the function (fn x=>exp), then f(arg) can be replaced by exp[x := arg]

3. Lists not arrays

4. Recursion not iteration

5. Higher-order functionsNew idioms, total procedural abstraction

Rewriting

fun square x = x * x;fun sos (x,y) = (square x) + (square y);

sos (3,4)==> (square 3) + (square 4) [Def’n of sos]==> 3*3 + (square 4) [Def’n of square]==> 9 + (square 4) [Def’n of *]==> 9 + 4*4 [Def’n of square]==> 9 + 16 [Def’n of *]==> 25 [Def’n of +]

Language of expressions only, no statements.

fun test (x) = if x>20 then "big" else "small"

test (sos (3,4))==> test(25)==> if 25>20 then "big" else "small"==> "big"

Canonical Value

Canonical value. A canonical value is one which cannot be rewrittenfurther.For example, 2+3 is not canonical, it evaluates to 5; 5 is a canonicalvalue.See canonical in the “The on-line hacker Jargon File,” version 4.4.7, 29Dec 2003.

History of Functional Languages

1959 LISP: List processing, John McCarthy

1975 Scheme: MIT

1977 FP: John Backus

1980 Hope: Burstall, McQueen, Sannella

1984 COMMON LISP: Guy Steele

1985 ML: meta-language (of LCF), Robin Milner

1986 Miranda: Turner

1990 Haskell: Hudak & Wadler editors

xkcd—a webcomic of romance, sarcasm, math, and language byRandall Munroe

Functional Languages

Lazy: don’t evaluate the function (constructor) arguments until needed(call-by-name), e.g., Haskell. Permits infinite data structures.Eager: call-by-value, e.g., ML

ML and Haskell

I Similar to ML: functional, strongly-typed, algebraic data types,type inferencing

I Differences: no references, exception handling, or side effects ofany kind; lazy evaluation, list comprehensions

Introduction to Haskell

1. Haskell (1.0) 1990

2. By 1997 four iterations of language design (1.4)

Salient Features of Haskell

1. Strongly-typed, lazy, functional language

2. Polymorphic types, type inference

3. Algebraic type definitions

4. Pattern matching function definitions

5. System of classes

6. Interactive

Information about Haskell

O’Sullivan, Goerzen, Stewart Real World Haskell

Hutton, Graham, Programming in Haskell.O’Donnell et al., Discrete Mathematics Using a Computer.

Introduction to SML

1. Robin Milner, Turing Award winner 1991

2. Metalanguage (ML) in Logic of Computable Functions (LCF)1980s

3. Actually general purpose language

4. SML definition 1990, revised 1997.

5. AT&T (D. McQueen), Princeton (A. Appel) implementation

Salient Features of SML

1. Strongly-typed, eager, functional language

2. Polymorphic types, type inference

3. Algebraic type definitions

4. Pattern matching function definitions

5. Exception handling

6. Module (signatures/structures) system

7. Interactive

Information about ML

Ullman, Jeffrey D. Elements of ML Programming. Second edition.Prentice-Hall, Upper Saddle River, New Jersey, 1998. 0-13-790387-1.

Paulson, Lawrence C. ML for the Working Programmer. Secondedition. Cambridge University Press, Cambridge, England, 1996.ISBN 0-521-56543-X.

Haskell

I Similar to ML: functional, strongly-typed, algebraic data types,type inferencing

I Differences: no references, exception handling, or side effects ofany kind; lazy evaluation, list comprehensions

fac n = if n==0 then 1 else n * fac (n-1)

data Tree = Leaf | Node (Tree , String, Tree)

size (Leaf) = 1size (Node (l,_,r)) = size (l) + size (r)

squares = [ n*n | n <- [0..] ]pascal = iterate (\row->zipWith (+) ([0]++row) (row++[0])) [1]

Haskell List Comprehension

[e | x1 <- l1, ..., xm <- lm, P1, ..., Pn]

e is an expression, xi is a variable, li is a list, Pi is a predicate

[ xˆ2 | x <- [ 1..10 ], even x][ xˆ2 | x <- [ 2,4..10 ] ][ x+y | x <- [1..3], y <- [1..4] ]

perms [] = [[]]perms x = [a:y | a<-x, y<-perms (x \\ [a]) ]

quicksort [] = []quicksort (s:xs) =quicksort[x|x<-xs,x<s]++[s]++quicksort[x|x<-xs,x>=s]

Patterns

Patterns are a very natural way of expression complex problems.Consider the code to re-balance red-black trees. This is usually quitecomplex to express in a programming language. But with patterns itcan be more concise. Notice that constructors of user-defined types(line RBTree) as well as pre-defined types (like list) can be used inpatterns.

data Color = R | B deriving (Show, Read)data RBTree a = Empty | T Color (RBTree a) a (RBTree a)deriving (Show, Read)

balance :: RBTree a -> a -> RBTree a -> RBTree abalance (T R a x b) y (T R c z d)=T R (T B a x b) y (T B c z d)balance (T R (T R a x b) y c) z d=T R (T B a x b) y (T B c z d)balance (T R a x (T R b y c)) z d=T R (T B a x b) y (T B c z d)balance a x (T R b y (T R c z d))=T R (T B a x b) y (T B c z d)balance a x (T R (T R b y c) z d)=T R (T B a x b) y (T B c z d)balance a x b = T B a x b

Functions

Prelude> : m Text.Show.FunctionsPrelude Text.Show.Functions > \x->x+1<function >Prelude Text.Show.Functions > :t \x->x+(1::Int)\x->x+(1::Int) :: Int -> IntPrelude Text.Show.Functions > :t \x->x+1\x->x+1 :: (Num a) => a -> a

Partial Application

Any curried function may be called with fewer arguments than it wasdefined for. The result is a function of the remaining arguments.If f is a function Int->Bool->Int->Bool, then

f :: Int->Bool->Int->Boolf 2 :: Bool->Int->Boolf 2 True :: Int->Boolf 2 True 3 :: Bool

Higher-order functions after lists.

Haskell Fold

“A tutorial on the universality and expressiveness of fold” by GrahamHutton.

Fold

foldr⊗

z[x1,x2, . . . ,xn] = x1

⊗(x2

⊗(. . .(xn

⊗z) . . .))

foldr f z [x1, x2, ..., xn] = x1 f (x2 f (...(xn f z)...))

Fold

foldl⊗

z[x1,x2, . . . ,xn] = (. . .((z⊗

x1)⊗

x2) . . .)⊗

xn

foldl f z [x1, x2, ..., xn] = (...((z f x1) f x2) ... ) f xn

Haskell Fold

foldr :: (b -> a -> a) -> a -> [b] -> afoldr f z [] = zfoldr f z (x:xs) = f x (foldr f z xs)

foldl :: (a -> b -> a) -> a -> [b] -> afoldl f z [] = zfoldl f z (x:xs) = foldl f (f z x) xs

foldl’ :: (a -> b -> a) -> a -> [b] -> afoldl’ f z0 xs = foldr f’ id xs z0

where f’ x k z = k $! f z x

[Real World Haskell says never use foldl instead use foldl’.]

Haskell Fold

Evaluates its first argument to head normal form, and then returns itssecond argument as the result.

seq :: a -> b -> b

Strict (call-by-value) application, defined in terms of ’seq’.

($!) :: (a -> b) -> a -> bf $! x = x ‘seq‘ f x

Haskell Fold

One important thing to note in the presence of lazy, ornormal-order evaluation, is that foldr will immediately returnthe application of f to the recursive case of folding over therest of the list. Thus, if f is able to produce some part of itsresult without reference to the recursive case, and the rest ofthe result is never demanded, then the recursion will stop.This allows right folds to operate on infinite lists. By contrast,foldl will immediately call itself with new parameters until itreaches the end of the list. This tail recursion can beefficiently compiled as a loop, but can’t deal with infinite listsat all – it will recurse forever in an infinite loop.

Haskell Fold

Another technical point to be aware of in the case of leftfolds in a normal-order evaluation language is that the newinitial parameter is not being evaluated before the recursivecall is made. This can lead to stack overflows when onereaches the end of the list and tries to evaluate the resultinggigantic expression. For this reason, such languages oftenprovide a stricter variant of left folding which forces theevaluation of the initial parameter before making therecursive call, in Haskell, this is the foldl’ (note theapostrophe) function in the Data.List library. Combined withthe speed of tail recursion, such folds are very efficient whenlazy evaluation of the final result is impossible orundesirable.

Haskell Fold

sum’ = foldl (+) 0product’ = foldl (*) 1and’ = foldl (&&) Trueor’ = foldl (||) Falseconcat’ = foldl (++) []composel = foldl (.) idcomposer = foldr (.) idlength = foldl (const (+1)) 0list_identity = foldr (:) []reverse’ = foldl (flip (:)) []unions = foldl Set.union Set.empty

Haskell Fold

reverse = foldl (\ xs x -> xs ++ [x]) []map f = foldl (\ xs x -> f x : xs) []filter p = foldl (\ xs x -> if p x then x:xs else xs) []

Haskell Fold

If this is your pattern

g [] = vg (x:xs) = f x (g xs)

then

g = foldr f v

Haskell Data Structures

data Bool = False | True

data Color = Red | Green | Bluederiving Show

data Day = Mon|Tue|Wed|Thu|Fri|Sat|Sunderiving (Show,Eq,Ord)

Types and constructors capitalized.Show allows Haskell to print data structures.

Haskell Data Structures

Constructors can take arguments.

data Shape = Circle Float | Rectangle Float Floatderiving Show

area (Circle r) = pi*r*rarea (Rectangle s1 s2) = s1*s2

Haskell Classes

next :: (Enum a, Bounded a, Eq a) => a -> anext x | x == maxBound = minBound| otherwise = succ x

Haskell Classes

data Triangle = Triangledata Square = Squaredata Octagon = Octagon

class Shape s wheresides :: s -> Integer

instance Shape Triangle wheresides _ = 3

instance Shape Square wheresides _ = 4

instance Shape Octagon wheresides _ = 8

Haskell Types

Type constructors can type types as parameters.

data Maybe a = Nothing | Just a

maybe :: b -> (a -> b) -> Maybe a -> bmaybe n _ Nothing = nmaybe _ f (Just x) = f x

data Either a b = Left a | Right b

either :: (a -> c) -> (b -> c) -> Either a b -> ceither f _ (Left x) = f xeither _ g (Right y) = g y

Haskell Lists

Data types can be recursive, as in lists:

data Nat = Nil | Succ Natdata IList = Nil | Cons Integer IListdata PolyList a = Nil | Cons a (PolyList a)

Haskell Trees

See Hudak PPT, Ch7.

data SimpleTree = SimLeaf | SimBranch SimpleTree SimpleTreedata IntegerTree = IntLeaf Integer |IntBranch IntegerTree IntegerTreedata InternalTree a = ILeaf |IBranch a (InternalTree a) (InternalTree a)data Tree a = Leaf a | Branch (Tree a) (Tree a)data FancyTree a b = FLeaf a |FBranch b (FancyTree a b) (FancyTree a b)data GTree = GTree [GTree]data GPTree a = GPTree a [GPTree a]

Nested Types

data List a = NilL | ConsL a (List a)data Nest a = NilN | ConsN a (Nest (a,a))data Bush a = NilB | ConsB a (Bush (Bush a))

data Node a = Node2 a a | Node3 a a adata Tree a = Leaf a | Succ (Tree (Node a))

Bird and Meertens, Nested Datatypes, 1998.Hinze, Finger Trees.

Haskell

input stream --> program --> output streamReal World

[Char] --> program --> [Char]Haskell World

module Main where

main = doinput <- getContentsputStr $ unlines $ f $ lines input

countWords :: String -> StringcountWords = unlines . format . count . words

count :: [String] -> [(String,Int)]count = map (\ws->(head ws, length ws)). groupBy (==). sort

Haskell

input stream --> program --> output streamReal World

[Char] --> program --> [Char]Haskell World

module Main where

main = interact countWords

countWords :: String -> StringcountWords = unlines . format . count . words

count :: [String] -> [(String,Int)]count = map (\ws->(head ws, length ws)). groupBy (==). sort