Haskell is a non-strict, purely functional programming language with strong static type inference. It supports recursive data types like Color, recursive functions on those types, parametric polymorphism with types like lists and Maybe, type classes for concepts like equality and ordering, and default definitions for type class methods. Type classes provide ad-hoc polymorphism and are more static than object-oriented classes.
6. Recursive Functions
hue :: Color -> Maybe Double
hue Red = Just 0
hue Green = Just 120
hue Blue = Just 240
7. hue (Mix c c') = case (hue c, hue c') of
(Just h, Just h') -> let
m = average h h'
m' = norm (m + 180)
d = distance h m
in case compare d 90 of
LT -> Just m
EQ -> Nothing
GT -> Just m'
_ -> Nothing
8. Parametric Data
data (a, b) = (a, b)
data Either a b = Left a | Right b
data Maybe a = Nothing | Just a
data [a] = [] | a:[a]
type String = [Char]
9. Parametric Functions
(.) :: (b -> c) -> (a -> b) -> a -> c
infixr . -- defaults to 9
(f . g) x = f (g x)
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
10. List Comprehensions
primitivePythagoreanTriples =
[ (a, b, c) | c <- nats, b <- [1..c], a <- [1..b],
a^2 + b^2 == c^2, gcd a b == 1]
primes = sieve [2..] where
sieve (p:xs) =
p : sieve [x | x <- xs, rem x p /= 0]
12. Membership Test
infix 4 `elem`
x `elem` xs = case filter (== x) xs of
[] -> False
_ -> True
'q' `elem` a_z --> True
'8' `elem` a_z --> False
13. Membership Test
elem :: a -> [a] -> Bool
infix 4 `elem`
x `elem` xs = case filter (== x) xs of
[] -> False
_ -> True
'q' `elem` a_z --> True
'8' `elem` a_z --> False
14. Membership Test
elem :: a -> [a] -> Bool
infix 4 `elem`
x `elem` xs = case filter (== x) xs of
[] -> False
_ -> True
'q' `elem` a_z --> True
'8' `elem` a_z --> False
15. Membership Test
elem :: a -> [a] -> Bool
infix 4 `elem`
x `elem` xs = case filter (== x) xs of
[] -> False
_ -> True
'q' `elem` a_z --> True
'8' `elem` a_z --> False
16. Membership Test
elem :: a -> [a] -> Bool
infix 4 `elem`
x `elem` xs = case filter (== x) xs of
[] -> False
_ -> True
'q' `elem` a_z --> True
'8' `elem` a_z --> False
17. Membership Test
elem :: a -> [a] -> Bool
infix 4 `elem`
x `elem` xs = case filter (== x) xs of
[] -> False
(==) :: Eq a => a -> a -> Bool
_ -> True
'q' `elem` a_z --> True
'8' `elem` a_z --> False
18. Membership Test
elem :: a -> [a] -> Bool
infix 4 `elem`
x `elem` xs = case filter (== x) xs of
[] -> False
(==) :: Eq a => a -> a -> Bool
_ -> True
'q' `elem` a_z --> True
'8' `elem` a_z --> False
19. Membership Test
elem :: a -> [a] -> Bool
infix 4 `elem`
x `elem` xs = case filter (== x) xs of
[] -> False
_ -> True
'q' `elem` a_z --> True
'8' `elem` a_z --> False
20. Membership Test
elem :: Eq a => a -> [a] -> Bool
infix 4 `elem`
x `elem` xs = case filter (== x) xs of
[] -> False
_ -> True
'q' `elem` a_z --> True
'8' `elem` a_z --> False
21. Membership Test
elem :: Eq a => a -> [a] -> Bool
infix 4 `elem`
x `elem` xs = case filter (== x) xs of
[] -> False
_ -> True
'q' `elem` a_z --> True
'8' `elem` a_z --> False
22. Eq Instance
instance Eq Color where
Red == Red = True
Green == Green = True
Blue == Blue = True
Mix c c' == Mix d d' = c == d && c' == d'
_ == _ = False
23. Eq Instance
instance Eq Color where
Red == Red = True
Green == Green = True
Blue == Blue = True
Mix c c' == Mix d d' = c == d && c' == d'
_ == _ = False
24. Eq Instance
ghci> :i Color
instance Eq Color where
Red == Red = True
Green == Green = True
Blue == Blue = True
Mix c c' == Mix d d' = c == d && c' == d'
_ == _ = False
25. ghci> :i Color
data Color = Red | Green | Blue | Mix
Color Color
! Defined at example.hs:1:6-10
--
instance Eq Color -- Defined at
example.hs:3:10-17
ghci>
26. ghci> :i Color
data Color = Red | Green | Blue | Mix
Color Color
! Defined at example.hs:1:6-10
--
instance Eq Color -- Defined at
example.hs:3:10-17
ghci> :i Eq
27. Default Definitions
ghci> :i Color
data Color = Red | Green | Blue | Mix
Color Color
! Eq a where example.hs:1:6-10
-- Defined at
class
instance Eq Color -- Defined at
(==), (/=) :: a -> a -> Bool
example.hs:3:10-17
ghci> :i=Eq (x == y)
x /= y not
class Eq=anot (x /= y)
x == y where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
! Defined in GHC.Classes
--
... followed by 26 instances ...
31. Default Definitions
ghci> :i Color
data Color = Red | Green | Blue | Mix
Color Color
! Eq a where example.hs:1:6-10
-- Defined at
class
instance Eq Color -- Defined at
(==), (/=) :: a -> a -> Bool
example.hs:3:10-17
ghci> :i=Eq (x == y)
x /= y not
class Eq=anot (x /= y)
x == y where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
! Defined in GHC.Classes
--
... followed by 26 instances ...
32. ... some Eq instances ...
instance Eq Color
instance Eq Bool
instance Eq Char
33. ... some Eq instances ...
instance Eq Color
instance Eq Bool
instance Eq Char
instance Eq a => Eq [a]
instance (Eq a, Eq b) => Eq (a, b)
37. Ord Instance
ghci> :t compare
compare :: Ord a => a -> a -> Ordering
ghci> :i Ord
class Eq a Color where
instance Ord => Ord a where
! Red
compare :: a -> a -> Ordering
<= _ = True
! Green::<= -> a -> = False
(<) a Red Bool
! Green :: a_-> a -> Bool
(>=) <= = True
! Blue ::<= -> a -> = False
(>) a Red Bool
! Blue :: aGreen -> Bool
(<=) <= -> a = False
Blue <= _ = True
! max :: a -> a -> a
Mix c c' <= Mix d d'
! min :: a -> a -> a
| c == d = c' <= d'
-- Defined in GHC.Classes
| otherwise = c <= d
_ <= _ = False
38. Ord Instance
instance Ord Color where
Red <= _ = True
Green <= Red = False
Green <= _ = True
Blue <= Red = False
Blue <= Green = False
Blue <= _ = True
Mix c c' <= Mix d d'
| c == d = c' <= d'
| otherwise = c <= d
_ <= _ = False
39. Ord Instance
instance Ord Color where
Red <= _ = True
Green <= Red = False
Green <= _ = True
Blue <= Red = False
Blue <= Green = False
Blue <= _ = True
Mix c c' <= Mix d d'
| c == d = c' <= d'
| otherwise = c <= d
_ <= _ = False
44. ghci> show (Mix Red Green)
"Mix Red Green"
ghci> read "Mix Red Green"
45. ghci> show (Mix Red Green)
"Mix Red Green"
ghci> read "Mix Red Green"
<interactive>:1:1:
Ambiguous type variable `a0' in the
constraint:
(Read a0) arising from a use of
`read'
Probable fix: add a type signature
that fixes these type variable(s)
In the expression: read "Mix Red
Green"
In an equation for `it': it = read
"Mix Red Green"
46. ghci> show (Mix Red Green)
"Mix Red Green"
ghci> read "Mix Red Green"
<interactive>:1:1:
Ambiguous type variable `a0' in the
constraint:
(Read a0) arising from a use of
`read'
Probable fix: add a type signature
that fixes these type variable(s)
In the expression: read "Mix Red
Green"
In an equation for `it': it = read
"Mix Red Green"
47. ghci> show (Mix Red Green)
"Mix Red Green"
ghci> read "Mix Red Green"
<interactive>:1:1:
Ambiguous type variable `a0' in the
constraint:
(Read a0) arising from a use of
`read'
Probable fix: add a type signature
that fixes these type variable(s)
In the expression: read "Mix Red
Green"
In an equation for `it': it = read
"Mix Red Green"
51. ghci> :t read
read :: Read a => String -> a
ghci> hue (read "Mix Red Green")
52. ghci> :t read
read :: Read a => String -> a
ghci> hue (read "Mix Red Green")
60.0
ghci>
53. ghci> :t read
read :: Read a => String -> a
ghci> hue (read "Mix Red Green")
60.0
ghci> read "Mix Red Green"
54. ghci> :t read
read :: Read a => String -> a
ghci> hue (read "Mix Red Green")
60.0
ghci> read "Mix Red Green" :: Color
55. Type Classes Compared
ghci> :t read
read :: Read a => String -> a
ghci> hue (read "Mix Red Green")
60.0
ghci> read "Mix Red Green" :: Color
Mix Red Green
ghci>
58. Type Classes Compared
OO Class Type Class
Type
Instance Object
(Not Value)
Dynamic Static on Any Part
Dispatch
on Receiver (Like Overloading)
Class Conditions
Extension Subclassing
(No Subtypes)
Default
Reuse Inheritance
(No Overriding)
59. Type Classes Compared
OO Class Type Class
Type
Instance Object
(Not Value)
Dynamic Static on Any Part
Dispatch
on Receiver (Like Overloading)
Class Conditions
Extension Subclassing
(No Subtypes)
Default
Reuse Inheritance
(No Overriding)
60. Type Classes Compared
OO Class Type Class
Type
Instance Object
(Not Value)
Dynamic Static on Any Part
Dispatch
on Receiver (Like Overloading)
Class Conditions
Extension Subclassing
(No Subtypes)
Default
Reuse Inheritance
(No Overriding)
61. Type Classes Compared
OO Class Type Class
Type
Instance Object
(Not Value)
Dynamic Static on Any Part
Dispatch
on Receiver (Like Overloading)
Class Conditions
Extension Subclassing
(No Subtypes)
Default
Reuse Inheritance
(No Overriding)
62. Type Classes Compared
OO Class Type Class
Type
Instance Object
(Not Value)
Dynamic Static on Any Part
Dispatch
on Receiver (Like Overloading)
Class Conditions
Extension Subclassing
(No Subtypes)
Default
Reuse Inheritance
(No Overriding)
63. Type Classes Compared
OO Class Type Class
Type
Instance Object
(Not Value)
Dynamic Static on Any Part
Dispatch
on Receiver (Like Overloading)
Class Conditions
Extension Subclassing
(No Subtypes)
Default
Reuse Inheritance
(No Overriding)
64. Type Classes Compared
OO Class Type Class
Type
Instance Object
(Not Value)
Dynamic Static on Any Part
Dispatch
on Receiver (Like Overloading)
Class Conditions
Extension Subclassing
(No Subtypes)
Default
Reuse Inheritance
(No Overriding)
65. Type Classes Compared
OO Class Type Class
Type
Instance Object
(Not Value)
Dynamic Static on Any Part
Dispatch
on Receiver (Like Overloading)
Class Conditions
Extension Subclassing
(No Subtypes)
Default
Reuse Inheritance
(No Overriding)
66. Type Classes Compared
OO Class Type Class
Type
Instance Object
(Not Value)
Dynamic Static on Any Part
Dispatch
on Receiver (Like Overloading)
Class Conditions
Extension Subclassing
(No Subtypes)
Default
Reuse Inheritance
(No Overriding)
71. numberFromString :: Num a => String -> a
numberFromString [] = 0
numberFromString (c:cs) =
fromIntegral (digitToInt c) *
10 ^ fromIntegral (length cs) +
integerFromString cs
72. numberFromString :: Num a => String -> a
numberFromString [] = 0
numberFromString (c:cs) =
fromIntegral (digitToInt c) *
10 ^ fromIntegral (length cs) +
integerFromString cs
fromIntegral ::
(Num b, Integral a) => a -> b
78. hue (Mix c c') = case (hue c, hue c') of
(Just h, Just h') -> let
m = average h h'
m' = norm (m + 180)
d = distance h m
in case compare d 90 of
LT -> Just m
EQ -> Nothing
GT -> Just m'
_ -> Nothing
79. hue (Mix c c') = case (hue c, hue c') of
(Just h, Just h') -> ...
_ -> Nothing
80. hue (Mix c c') = case hue c of
Just h -> case hue c' of
Just h' -> ...
Nothing -> Nothing
Nothing -> Nothing
81. hue (Mix c c') = case hue c of
Just h -> hue c' >>= h' -> ...
Nothing -> Nothing
82. hue (Mix c c') = hue c >>= h ->
hue c' >>= h' -> ...
83. hue (Mix c c') = hue c >>= h ->
do h' <- hue c'; ...
84. hue (Mix c c') = do h <- hue c
do h' <- hue c'; ...
85. hue (Mix c c') = do
h <- hue c
h' <- hue c'
...
86. hue (Mix c c') = do
h <- hue c
h' <- hue c'
let
m = average h h'
m' = norm (m + 180)
d = distance h m
in case compare d 90 of
LT -> Just m
EQ -> Nothing
GT -> Just m'
87. hue (Mix c c') = do
h <- hue c
h' <- hue c'
let
m = average h h'
m' = norm (m + 180)
d = distance h m
case compare d 90 of
LT -> Just m
EQ -> Nothing
GT -> Just m'
89. [ (a, b, c) | c <- nats, b <- [1..c], a <- [1..b]]
90. [ (a, b, c) | c <- nats, b <- [1..c], a <- [1..b]]
do
c <- nats
b <- [1..c]
a <- [1..b]
return (a, b, c)
91. Generalized Map
(<$>) :: Monad m => (a -> b) -> m a -> m b
f <$> m = m >>= return . f
ord <$> "abc" --> [97, 98, 99]
92. Constant Map
(<$) :: Monad m => a -> m b -> m a
(<$) = (<$>) . const
'x' <$ "abc" --> "xxx"
93. [ (a, b, c) | c <- nats, b <- [1..c], a <- [1..b]]
do
c <- nats
b <- [1..c]
a <- [1..b]
return (a, b, c)
94. [ (a, b, c) | c <- nats, b <- [1..c], a <- [1..b],
a^2 + b^2 == c^2]
do
c <- nats
b <- [1..c]
a <- [1..b]
guard $ a^2 + b^2 == c^2
return (a, b, c)
101. Derived Action
getLine :: Getter String
getLine = do
c <- getChar
if c == 'n' || c == '0'
then return ""
else do
s <- getLine
return $ c:s
get getLine "hellonworld" --> ("hello", "world")
102. IO
data IO a = IO (RealWorld -> (a, RealWorld))
putChar :: Char -> IO ()
112. Parsers
instance MonadPlus Parser where
mzero = Parser $ s -> []
mplus p q = Parser $ s ->
parse p s ++ parse q s
(<|>) :: Parser a -> Parser a -> Parser a
infixr 1 <|>
(<|>) = mplus
113. Primitive Actions
anyChar :: Parser Char
anyChar = Parser $ s -> case s of
c:cs -> [(c, cs)]
"" -> []
eof :: Parser ()
eof = Parser $ s -> case s of
c:cs -> []
"" -> [((), "")]
114. Derived Actions
satisfy :: (Char -> Bool) -> Parser Char
satisfy f = do
c <- anyChar
if f c
then return c
else mzero
148. frac :: Parser Double
frac = option 0 $ do
char '.'
n <- digits
return $ numberFromString n / 10 ^^ length n
expon :: Parser Double
expon = option 1 $ do
eE
s <- sign
n <- digits
return $ s * 10 ** numberFromString n