67
Haskell in the Real World Functional Programming Night Geekup Liverpool, 31 st May, 2011 [email protected] http://www.fickr.com/photos/jef_saf/3493852795/

Haskell in the Real World

Embed Size (px)

DESCRIPTION

A short talk on what makes Functional Programming - and especially Haskell - different.We'll take a quick overview of Haskell's features and coding style, and then work through a short but complete example of using it for a Real World problem.http://lanyrd.com/2011/geekup-liverpool-may/sdykh/

Citation preview

Page 1: Haskell in the Real World

Haskell in the Real World

Functional Programming Night

Geekup Liverpool, 31st May, [email protected]

http://www.fickr.com/photos/jef_saf/3493852795/

Page 2: Haskell in the Real World

What makes FP different?

● MJD quoting Norvig (on Lisp):● “big, important features, features like frst-class

functions, dynamic access to the symbol table, and automatic storage management.”

● gluing functions together● declarative

Page 3: Haskell in the Real World

Popular FP languages

● Excel● SQL?● Linq (based on Haskell's monads)● Lisp → Scheme → Clojure● Strongly Typed FP (Hindley/Milner)

● ML → Ocaml → F#● Haskell

Page 4: Haskell in the Real World

What makes Haskell different?

● Purity● Laziness● High Level● Strong Typing● Memory Managed● Modular● Mathematical rigour

● category theory

Page 5: Haskell in the Real World

Sounds a bit ivory tower?

● http://prog21.dadgum.com/31.html

● Q “When will Haskell fnally go mainstream?”

● A “most of it already has.”

Page 6: Haskell in the Real World

Imperative programming● records = [ "one", "two", "three", "four", "five" ]

filtered = []; j = 0;

for (i = 0; i < length records; i++) {

if (records[i] matches “o”) {

filtered[j++] = records[i];}

}

Page 7: Haskell in the Real World

Imperative programming● records = [ "one", "two", "three", "four", "five" ]

filtered = []; j = 0;

for (i = 0; i < length records; i++) {

if (records[i] matches “o”) {

filtered[j++] = records[i];}

}

Page 8: Haskell in the Real World

Functional version

● filtered = filter (=~ “o”) records

Page 9: Haskell in the Real World

Why is this better?

● less code. less bugs● no synthetic variables

● i, j, length records● no risk of off-by-one error● intent clear from skimming● intent clear to compiler● parallelize (MapReduce, Hadoop)

Page 10: Haskell in the Real World

Why is this better?

● fewer codes. fewer bugs● no synthetic variables

● i, j, length records● no risk of off-by-one error● intent clear from skimming● intent clear to compiler● parallelize (MapReduce, Hadoop)

Page 11: Haskell in the Real World

Your language has this construct

● Perl: my @filtered = grep /o/, @records;● .Net: var filtered = from r in records where r.match('o') select r

● Ruby: @filtered = @records.grep /o/● Python: filtered = [x for x in records if re.match('o', x)]

● etc.

Page 12: Haskell in the Real World

Another example

● countCaps = length . filter (isUpper . head) . words

> countCaps “Hello there, Fred” 2

Page 13: Haskell in the Real World

Real World Haskell

● JSON library● barcode reading● database

Page 14: Haskell in the Real World

Quizzes

● important subsystem of Makini's attention management system

● real world (has customers, pays wages)● currently written in Perl● could it be ported to Haskell?

Page 15: Haskell in the Real World

Haskell Quiz – proof of concept

● full code at:● https://github.com/

osfameron/geekup-talk-haskell/

● overview, to give a favour of programming in Haskell

Page 16: Haskell in the Real World

Modelling the quiz

Page 17: Haskell in the Real World

Modelling the quiz

Page 18: Haskell in the Real World

Modelling the quiz

Page 19: Haskell in the Real World

Modelling the quiz

2x

Page 20: Haskell in the Real World

Modelling the quiz

Page 21: Haskell in the Real World

Modelling the quiz

1x

Page 22: Haskell in the Real World

Quiz tree data types

● Quizzes● Sections

● (randomized sections)

● Questions

Page 23: Haskell in the Real World

Quiz data type● data QuizNode = Quiz Name [QuizNode] | Section Name Score [QuizNode] | RandomSection Name Score Choose [QuizNode] | Question Name Score Answer

Page 24: Haskell in the Real World

Quiz data type● data QuizNode = Quiz Name [QuizNode] | Section Name Score [QuizNode] | RandomSection Name Score Choose [QuizNode] | Question Name Score Answer

● type Name = String

type Score = Inttype Choose = Int

Page 25: Haskell in the Real World

Quiz data type● data QuizNode = Quiz Name [QuizNode] | Section Name Score [QuizNode] | RandomSection Name Score Choose [QuizNode] | Question Name Score Answer

● data Answer = MultiChoice [BoolAnswer] | StringChoice [String]

Page 26: Haskell in the Real World

Quiz data type● data QuizNode = Quiz Name [QuizNode] | Section Name Score [QuizNode] | RandomSection Name Score Choose [QuizNode] | Question Name Score Answer

● data Answer = MultiChoice [BoolAnswer] | StringChoice [String]

● data BoolAnswer = BoolAnswer Bool String

Page 27: Haskell in the Real World

Quiz data typequiz,geo,pop :: QuizNodequiz = Quiz “General Knowledge Quiz” [ pop, geo ]

geo = RandomSection “Geography” 40 2 [ Question “What is the capital of England?” 2 $ StringChoice [“London”], Question “What is the capital of France?” 2 $ StringChoice [“Paris”], Question “What is the capital of Finland?” 2 $ StringChoice [“Helsinki”], Question “What is the capital of Italy?” 2 $ StringChoice [“Rome”, “Roma”], ]

Page 28: Haskell in the Real World

Quiz data typequiz,geo,pop :: QuizNodequiz = Quiz “General Knowledge Quiz” [ pop, geo ]

geo = RandomSection “Geography” 40 2 [ Question “What is the capital of England?” 2 $ StringChoice [“London”], Question “What is the capital of France?” 2 $ StringChoice [“Paris”], Question “What is the capital of Finland?” 2 $ StringChoice [“Helsinki”], Question “What is the capital of Italy?” 2 $ StringChoice [“Rome”, “Roma”], ]

Page 29: Haskell in the Real World

Quiz data typequiz,geo,pop :: QuizNodequiz = Quiz “General Knowledge Quiz” [ pop, geo ]

geo = RandomSection “Geography” 40 2 [ Question “What is the capital of England?” 2 $ StringChoice [“London”], Question “What is the capital of France?” 2 $ StringChoice [“Paris”], Question “What is the capital of Finland?” 2 $ StringChoice [“Helsinki”], Question “What is the capital of Italy?” 2 $ StringChoice [“Rome”, “Roma”], ]

Page 30: Haskell in the Real World

Quiz data typepop = Section “Pop music” 60 [ Question “Which of these are Beatles?” 5 $ MultiChoice [ y “John”, y “Paul”, y “George”, y “Ringo”, n “Bob”, n “Jason” ], ...

Page 31: Haskell in the Real World

Quiz data typepop = Section “Pop music” 60 [ Question “Which of these are Beatles?” 5 $ MultiChoice [ BoolAnswer True “John”, BoolAnswer True “Paul”, BoolAnswer True “George”, BoolAnswer True “Ringo”, BoolAnswer False “Bob”, BoolAnswer False “Jason” ], ...

Page 32: Haskell in the Real World

Quiz data typepop = Section “Pop music” 60 [ Question “Which of these are Beatles?” 5 $ MultiChoice [ y “John”, y “Paul”, y “George”, y “Ringo”, n “Bob”, n “Jason” ], ...

y,n :: String -> BoolAnswery = BoolAnswer Truen = BoolAnswer False

Page 33: Haskell in the Real World

Stamping the quiz

1x 2x

Page 34: Haskell in the Real World

Stamping the quiz

1x 2x

Page 35: Haskell in the Real World

Stamping the quiz

1x

stamp :: QuizNode → ...

2x

Page 36: Haskell in the Real World

Stamping the quiz

1x

stamp :: QuizNode → QuizNode?

2x

Page 37: Haskell in the Real World

Functions

● increment :: Num → Num● increment 4 => 5● increment 10 => 11

Page 38: Haskell in the Real World

Functions

● increment :: Num → Num● increment 4 => 5● increment 10 => 11

Page 39: Haskell in the Real World

Functions

● increment :: Num → Num● increment 4 => 5● increment 10 => 11

Page 40: Haskell in the Real World

Functions

● increment :: Num → Num● increment x = x+1

Page 41: Haskell in the Real World

Functions

let x = 42

addx :: Num → Numadd y = x + y

Page 42: Haskell in the Real World

Functions

let x = 42

addx :: Num → Numadd y = x + y

(cannot change!)

Page 43: Haskell in the Real World

Functions

let x = 42

addx :: Num → Numadd y = x + y

Page 44: Haskell in the Real World

Stamping the quiz

1x

stamp :: QuizNode → QuizNode?

2x

Page 45: Haskell in the Real World

Stamping the quiz

1x

stamp :: QuizNode → QuizNode?

2x

Page 46: Haskell in the Real World

Stamping the quiz

1x

stamp :: QuizNode → IO QuizNode

2x

Page 47: Haskell in the Real World

Monads

● Useful data-structure● Lets us model various thing...

● including IO in a pure language● Concept is a little confusing● Using them is (mostly) not too bad.

Page 48: Haskell in the Real World

Stamping the quizstamp :: QuizNode → IO QuizNode

Page 49: Haskell in the Real World

Stamping the quiz

1x 2x

stamp :: QuizNode → IO QuizNode

Page 50: Haskell in the Real World

Stamping the quiz

1x 2x

stamp :: QuizNode → IO QuizNode

Page 51: Haskell in the Real World

Stamping the quizstamp :: QuizNode → IO QuizNode

Page 52: Haskell in the Real World

Stamping the quizstamp :: QuizNode → IO QuizNode

Page 53: Haskell in the Real World

The stamp function

stamp :: QuizNode -> IO QuizNode

stamp q@(Question _ _ _) = return q

stamp (Quiz s ns) = Quiz s <$> mapM stamp nsstamp (Section s i ns) = Section s i <$> mapM stamp ns

stamp (RandomSection s i r ns) = do selected <- pickN r ns Section s i <$> mapM stamp selected

Page 54: Haskell in the Real World

The stamp function

stamp :: QuizNode -> IO QuizNode

stamp q@(Question _ _ _) = return q

stamp (Quiz s ns) = Quiz s <$> mapM stamp nsstamp (Section s i ns) = Section s i <$> mapM stamp ns

stamp (RandomSection s i r ns) = do selected <- pickN r ns Section s i <$> mapM stamp selected

Page 55: Haskell in the Real World

The stamp function

stamp :: QuizNode -> IO QuizNode

stamp q@(Question _ _ _) = return q

stamp (Quiz s ns) = Quiz s <$> mapM stamp nsstamp (Section s i ns) = Section s i <$> mapM stamp ns

stamp (RandomSection s i r ns) = do selected <- pickN r ns Section s i <$> mapM stamp selected

map stamp ns– “stamp all the child nodes in turn”

Page 56: Haskell in the Real World

The stamp function

stamp :: QuizNode -> IO QuizNode

stamp q@(Question _ _ _) = return q

stamp (Quiz s ns) = Quiz s <$> mapM stamp nsstamp (Section s i ns) = Section s i <$> mapM stamp ns

stamp (RandomSection s i r ns) = do selected <- pickN r ns Section s i <$> mapM stamp selected

Page 57: Haskell in the Real World

The stamp function

stamp :: QuizNode -> IO QuizNode

stamp q@(Question _ _ _) = return q

stamp (Quiz s ns) = Quiz s <$> mapM stamp nsstamp (Section s i ns) = Section s i <$> mapM stamp ns

stamp (RandomSection s i r ns) = do selected <- pickN r ns Section s i <$> mapM stamp selected

1x

Page 58: Haskell in the Real World

Taking the quiz!

● takeNode :: QuizNode -> IO CompletedNode

● printQuestion :: QuizNode -> IO ()

● showBoolTextAnswers :: [BoolAnswer] -> String

● checkAnswer :: String -> Answer -> Bool

Page 59: Haskell in the Real World

Taking the quiz!

● takeNode :: QuizNode -> IO CompletedNode

● printQuestion :: QuizNode -> IO ()

● showBoolTextAnswers :: [BoolAnswer] -> String

● checkAnswer :: String -> Answer -> Bool

Page 60: Haskell in the Real World

Taking the quiz!

● takeNode :: QuizNode -> IO CompletedNode

● printQuestion :: QuizNode -> IO ()

● showBoolTextAnswers :: [BoolAnswer] -> String

● checkAnswer :: String -> Answer -> Bool

Page 61: Haskell in the Real World

Taking the quiz!

● takeNode :: QuizNode -> IO CompletedNode

● printQuestion :: QuizNode -> IO ()

● showBoolTextAnswers :: [BoolAnswer] -> String

● checkAnswer :: String -> Answer -> Bool

Page 62: Haskell in the Real World

takeNode

takeNode node@(Question s i a) = do printQuestion node ans <- getLine let correct = checkAnswer ans a let score = if correct

then (i,i) else (0,i) putStrLn $ if correct

then “Correct!” else “Wrong!” return $

CompletedNode ans score [] node

Page 63: Haskell in the Real World

main

main :: IO ()main = stamp quiz >>= takeQuiz

Function, not entrypoint

Page 64: Haskell in the Real World

main

main :: IO ()main = stamp quiz >>= takeQuiz

Live Demo!

Page 65: Haskell in the Real World

Should you go Haskell?

● Power● Speed?

● can be faster than C (supercompilation)● can be tricky to optimize

● Jobs?● In NorthWestUK?

● Libraries & Tools● Haskell Platform. Hackage. Cabal

Page 66: Haskell in the Real World

Should you learn Haskell?

● Powerful● Interesting techniques● … and ways of thinking about problems● Ready for future shift to FP● … possibly in your own language

Page 67: Haskell in the Real World

Thank you! Questions?

● full code at:● https://github.com/

osfameron/geekup-talk-haskell/

[email protected]

http://www.fickr.com/photos/jef_saf/3493852795/