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/
1. Haskell in the Real World
Functional Programming Night
Geekup Liverpool, 31st May, 2011
hakim.cassimally@gmail.com
http://www.fickr.com/photos/jef_saf/3493852795/
2. 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
3. Popular FP languages
● Excel
● SQL?
● Linq (based on Haskell's monads)
● Lisp → Scheme → Clojure
● Strongly Typed FP (Hindley/Milner)
● ML → Ocaml → F#
● Haskell
4. What makes Haskell different?
● Purity
● Laziness
● High Level
● Strong Typing
● Memory Managed
● Modular
● Mathematical rigour
● category theory
5. Sounds a bit ivory tower?
●
http://prog21.dadgum.com/31.html
● Q “When will Haskell fnally go
mainstream?”
● A “most of it already has.”
6. 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];
}
}
7. 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];
}
}
9. 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)
10. 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)
11. 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.
12. Another example
●
countCaps = length
. filter (isUpper . head)
. words
> countCaps “Hello there, Fred”
2
14. 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?
15. Haskell Quiz – proof of concept
● full code at:
●
https://github.com/
osfameron/geekup-talk-haskell/
● overview, to give a favour of programming
in Haskell
22. Quiz tree data types
● Quizzes
● Sections
● (randomized sections)
● Questions
23. Quiz data type
●
data QuizNode =
Quiz Name [QuizNode]
| Section Name Score [QuizNode]
| RandomSection Name Score Choose [QuizNode]
| Question Name Score Answer
24. 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 = Int
type Choose = Int
25. 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]
26. 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
27. Quiz data type
quiz,geo,pop :: QuizNode
quiz = 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”],
]
28. Quiz data type
quiz,geo,pop :: QuizNode
quiz = 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”],
]
29. Quiz data type
quiz,geo,pop :: QuizNode
quiz = 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”],
]
30. Quiz data type
pop = Section “Pop music” 60 [
Question “Which of these are Beatles?” 5
$ MultiChoice [
y “John”,
y “Paul”,
y “George”,
y “Ringo”,
n “Bob”,
n “Jason” ],
...
31. Quiz data type
pop = 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” ],
...
32. Quiz data type
pop = 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 -> BoolAnswer
y = BoolAnswer True
n = BoolAnswer False
47. 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.
53. The stamp function
stamp :: QuizNode -> IO QuizNode
stamp q@(Question _ _ _) = return q
stamp (Quiz s ns) = Quiz s <$> mapM stamp ns
stamp (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
54. The stamp function
stamp :: QuizNode -> IO QuizNode
stamp q@(Question _ _ _) = return q
stamp (Quiz s ns) = Quiz s <$> mapM stamp ns
stamp (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
55. The stamp function
map stamp ns
stamp :: QuizNode -> IO QuizNode – “stamp all the
child nodes in
stamp q@(Question _ _ _) = return q turn”
stamp (Quiz s ns) = Quiz s <$> mapM stamp ns
stamp (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
56. The stamp function
stamp :: QuizNode -> IO QuizNode
stamp q@(Question _ _ _) = return q
stamp (Quiz s ns) = Quiz s <$> mapM stamp ns
stamp (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
57. The stamp function
stamp :: QuizNode -> IO QuizNode
stamp q@(Question _ _ _) = return q
stamp (Quiz s ns) = Quiz s <$> mapM stamp ns
stamp (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
62. 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
63. main
main :: IO ()
main = stamp quiz >>= takeQuiz
Function, not entrypoint
64. main
main :: IO ()
main = stamp quiz >>= takeQuiz
Live Demo!
65. 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
66. Should you learn Haskell?
● Powerful
● Interesting techniques
● … and ways of thinking about problems
● Ready for future shift to FP
● … possibly in your own language