We introduce Haskell. Why is it interesting. Where did it come from. What is it like. How to get started.
We show a GHCi session. We introduce simple recursive function and data. And we demo QuickCheck for testing properties of automatically generated data.
6. Why? Aesthetics
“We provided DARPA with a copy of our prototype
implemented in Haskell without explaining that it was
a program, and based on preconceptions from their
past experience, they had studied the program under
the assumption that it was a mixture of requirements
specification and top level design. They were
convinced it was incomplete because it did not address
issues such as data structure design and execution
order.”
— Paul Hudak
7. Why? Aesthetics
“Take Lisp: you know it's the most beautiful language
in the world. At least up until Haskell came along.”
— Larry Wall
23. Why? Pragmatics
“A programming language must be considered in the
context of its community, and Haskell has an
exemplary one. I have come to believe, however, that
this polite exterior conceals a deep and consuming
madness.”
— Avdi Grimm
39. Provide faster communication of new
ideas.
Stable foundation for real application
development.
Vehicle through which others would be
encouraged to use functional languages.
40. Who? When? Where?
Haskell Report
April 1st 1990
“You know, Haskell
actually never liked the
name Haskell.”
— Mary Curry
80. What? Monads
“Haskell is the world's finest
imperative programming language.”
— Simon Peyton-Jones
81. What? Monads
“Haskell is the only language I know with
first-class support for imperative programming.”
— SamB
82. What? Monads
“Haskell has no preferred imperative semantics, and
the monad just lets you swap out the semantics
according to your needs.”
— Jared Updike
100. What? Type Purity
No side effects
mean,
argument and return
types limit what
a function can do.
101. What? Type Purity
“Haskell is so strict about type safety that randomly
generated snippets of code that successfully type check
are likely to do something useful, even if you've no idea
what that useful thing is.”
— sigfpe
102. What? Type Purity
“Since when does "it compiles" equate to "it will run
(correctly)"? We're talking about C, after all, not
Haskell.”
— Sean Russell
128. "hello, world"
ghci> 6 * 9
42
ghci> [1, 2, 3]
[1,2,3] application is so important in Haskell that
“Function
ghci> it it using the quietest possible syntax:
we denote
[1,2,3]at all.”
nothing
ghci> reverse it
— Simon Peyton-Jones
129. “Function application is so important in Haskell that
we denote it using the quietest possible syntax:
nothing at all.”
— Simon Peyton-Jones
130. "hello, world"
ghci> 6 * 9
42
ghci> [1, 2, 3]
[1,2,3] application is so important in Haskell that
“Function
ghci> it it using the quietest possible syntax:
we denote
[1,2,3]at all.”
nothing
ghci> reverse it
— Simon Peyton-Jones
156. [22,23,⋯,99,100]
ghci> let divides = x y -> rem y x == 0
ghci> let divides x y = rem y x == 0
ghci> divides 3 12
True
ghci> 3 `divides` 12
157. [22,23,⋯,99,100]
ghci> let divides = x y -> rem y x == 0
ghci> let divides x y = rem y x == 0
ghci> divides 3 12
True
ghci> 3 `divides` 12
True
ghci>
158. [22,23,⋯,99,100]
ghci> let divides = x y -> rem y x == 0
ghci> let divides x y = rem y x == 0
ghci> divides 3 12
True
ghci> 3 `divides` 12
True
ghci> let divisors x = [d | d <- [1..x],
d `divides` x]
159. [22,23,⋯,99,100]
ghci> let divides = x y -> rem y x == 0
ghci> let divides x y = rem y x == 0
ghci> divides 3 12
True
ghci> 3 `divides` 12
True
ghci> let divisors x = [d | d <- [1..x],
d `divides` x]
ghci>
160. [22,23,⋯,99,100]
ghci> let divides = x y -> rem y x == 0
ghci> let divides x y = rem y x == 0
ghci> divides 3 12
True
ghci> 3 `divides` 12
True
ghci> let divisors x = [d | d <- [1..x],
d `divides` x]
ghci> divisors 100
161. [22,23,⋯,99,100]
ghci> let divides = x y -> rem y x == 0
ghci> let divides x y = rem y x == 0
ghci> divides 3 12
True
ghci> 3 `divides` 12
True
Fundamentals
ghci> let divisors x = [d | d <- [1..x],
d `divides` x]
ghci> divisors 100
[1,2,4,5,10,20,25,50,100]
ghci>
164. Variables
red = Red
-- Lower case for variable and upper case for
constructor.
nan = 0 / 0
-- Variables stand for values. They do not label
locations.
-- Don't need let because we aren't at GHCi.
-- Declarations go at top-level, not expressions.
(Like Java, unlike Ruby.)
170. Boolean Operators
True && x = x
False && _ = False
(||) True _ = True
(||) False x = x
-- Parenthesis let us use operators prefix.
171. Operator Precedence
infixr 3 &&
infixr 2 ||
-- Ten precedence levels: 0 binds least tightly, 9
(default) binds most tightly.
-- Three associativities: infixl (default), infixr,
infix (non-associative).
172. Types
“Types in Haskell express high-level design in the same
way that UML diagrams do in Object Oriented
languages.”
— Simon Peyton-Jones
173. Types
ghci> :l example
“Types in Haskell express high-level design in the same
way that UML diagrams do in Object Oriented
languages.”
— Simon Peyton-Jones
174. ghci> :l example
[1 of 1] Compiling Main
( example.hs, interpreted )
Ok, modules loaded: Main.
ghci>
175. ghci> :l example
[1 of 1] Compiling Main
( example.hs, interpreted )
Ok, modules loaded: Main.
ghci> :r
176. ghci> :l example
[1 of 1] Compiling Main
( example.hs, interpreted )
Ok, modules loaded: Main.
ghci> :r
Ok, modules loaded: Main.
ghci>
177. ghci> :l example
[1 of 1] Compiling Main
( example.hs, interpreted )
Ok, modules loaded: Main.
ghci> :r
Ok, modules loaded: Main.
ghci> :type red
178. ghci> :l example
[1 of 1] Compiling Main
( example.hs, interpreted )
Ok, modules loaded: Main.
ghci> :r
Ok, modules loaded: Main.
ghci> :type red
Red :: Color
ghci>
179. ghci> :l example
[1 of 1] Compiling Main
( example.hs, interpreted )
Ok, modules loaded: Main.
ghci> :r
Ok, modules loaded: Main.
ghci> :type red
Red :: Color
ghci> :t isRed
180. Types
ghci> :l example
[1 of 1] Compiling Main
( example.hs, interpreted )
Ok, :: Color loaded: Main.
red modules
ghci> Double
nan :: :r
Ok, modules loaded: Main.
ghci> Color -> Double
hue :: :type red
Red :: Color
otherwise :: Bool
ghci> :t isRed
isRed Bool -> Bool Bool
not :: :: Color ->
ghci> (||) :: Bool -> Bool -> Bool
(&&),
181. Types
red :: Color
nan :: Double
hue :: Color -> Double
otherwise :: Bool
not :: Bool -> Bool
(&&), (||) :: Bool -> Bool -> Bool
183. Recursive Data
data Color = Red | Green | Blue
| Mix Color Color
mix :: Color -> Color -> Color
mix = Mix
-- Mix is a type constructor function.
184. Recursive Data
yellow, cyan, magenta :: Color
yellow = Mix Red Green
Mix cyan magenta =
Mix (Mix Green Blue) (Mix Red Blue)
-- Constructor functions can be used for pattern
matching, but variables bind.
185. Recursive Functions
isRed :: Color -> Bool
isRed Red = True
isRed (Mix c c') = isRed c && isRed c'
isRed _ = False
192. h'
hue (Mix c c') = let
h = hue c
h' = hue c'
??? h
193. h' m
hue (Mix c c') = let
h = hue c
h' = hue c'
??? h
194. h' m
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
???
195. h' m
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
average x y = abs (x + y) / 2
???
196. h' m
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
average x y = abs (x + y) / 2
in m
197. h' m
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
average x y = abs (x + y) / 2
in ??!
198. m
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
average x y = abs (x + y) / 2
in ??!
h'
199. m
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
average x y = abs (x + y) / 2
in ??!
h' m'
200. m
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
m' = m + 180
average x y = abs (x + y) / 2
in ??!
h' m'
201. m d
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
m' = m + 180
average x y = abs (x + y) / 2
in ??!
h' m'
202. m d
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
m' = m + 180
d = distance h m
average x y = abs (x + y) / 2
in ??! h' m'
203. m d
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
m' = m + 180
d = distance h m
average x y = abs (x + y) / 2
distance x y = abs (x - y) h' m'
in ??!
204. m d
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
m' = m + 180
d = distance h m
average x y = abs (x + y) / 2
distance x y = abs (x - y) h' m'
in case compare d 90 of
LT -> m
EQ -> ??!
GT -> m'
205. m d
hue (Mix c c') = let
h = hue c
h' = hue c'
m = average h h' h
m' = m + 180
d = distance h m
average x y = abs (x + y) / 2
distance x y = abs (x - y) h' m'
in case compare d 90 of
LT -> m
EQ -> nan
GT -> m'
206. m d
hue (Mix c c') = r where
r = case compare d 90 of
LT -> m
EQ -> nan h
GT -> m'
h = hue c
h' = hue c'
m = average h h'
m' = m + 180 h' m'
d = distance h m
average x y = abs (x + y) / 2
distance x y = abs (x - y)
207. Testing
test-framework organize tests
HUnit what you’re used to
QuickCheck test properties with
automatically generated data
209. QuickCheck
prop_hue_bounds c = let h = hue c in
isNaN h || 0 <= h && h < 360
prop_hue_mix_reflexivity c = let h = hue c in
isNaN h || hue (Mix c c) == h
210. QuickCheck
prop_hue_bounds c = let h = hue c in
isNaN h || 0 <= h && h < 360
prop_hue_mix_reflexivity c = let h = hue c in
isNaN h || hue (Mix c c) == h
prop_hue_mix_commutativity c c' =
let h = hue (Mix c c') in
isNaN h || hue (Mix c' c) == h
211. QuickCheck
ghci> quickCheck prop_hue_mix_commutativi
ty
prop_hue_bounds c = let h = hue c in
isNaN h || 0 <= h && h < 360
prop_hue_mix_reflexivity c = let h = hue c in
isNaN h || hue (Mix c c) == h
prop_hue_mix_commutativity c c' =
let h = hue (Mix c c') in
isNaN h || hue (Mix c' c) == h
219. h'
hue (Mix c c') = r where
r = case compare d 90 of
LT -> m
EQ -> nan m m'
GT -> m'
h = hue c
h' = hue c'
m = average h h'
d h
m' = m + 180
d = distance h m
220. h'
hue (Mix c c') = r where
r = case compare d 90 of
LT -> m
EQ -> nan m m'
GT -> m'
h = hue c
h' = hue c'
m = average h h'
d h
m' = normalize (m + 180)
d = distance h m
221. h'
hue (Mix c c') = r where
r = case compare d 90 of
LT -> m
EQ -> nan m m'
GT -> m'
h = hue c
h' = hue c'
m = average h h'
d h
m' = normalize (m + 180)
d = distance h m
normalize h | h < 360 = h
| otherwise = h - 360
222. h'
hue (Mix c c') = r where
r = case compare d 90 of
LT -> m
EQ -> nan m m'
GT -> m'
h = hue c
h' = hue c'
m = average h h'
d h
m' = normalize (m + 180)
d = distance h m
normalize h | h < 360 = h
| otherwise = normalize (h - 360)
223. ghci> h'
hue (Mix c c') = r where
r = case compare d 90 of
LT -> m
EQ -> nan m m'
GT -> m'
h = hue c
h' = hue c'
m = average h h'
d h
m' = normalize (m + 180)
d = distance h m
normalize h | h < 360 = h
| otherwise = normalize (h - 360)
230. QuickCheck
prop_hue_mix_nothing c c' =
distance (hue c) (hue c') == 180 ==>
isNaN (hue (Mix c c'))
-- Can we easily find the complement of a color?
231. complement Red = ???
complement Green = ???
complement Blue = ???
complement (Mix c c') = ???
232. complement Red = cyan
complement Green = ???
complement Blue = ???
complement (Mix c c') = ???
233. complement Red = cyan
complement Green = magenta
complement Blue = ???
complement (Mix c c') = ???
234. complement Red = cyan
complement Green = magenta
complement Blue = yellow
complement (Mix c c') = ???
235. complement Red = cyan
complement Green = magenta
complement Blue = yellow
complement (Mix c c') = Mix ???
???
236. complement Red = cyan
complement Green = magenta
complement Blue = yellow
complement (Mix c c') = Mix (complement c )
(complement c' )
238. QuickCheck
prop_complement c = let h = hue c in
not (isNaN h) ==>
distance h (hue (complement c)) == 180
prop_hue_mix_complement c =
isNaN (hue (Mix c (complement c)))