Upcoming SlideShare
×

1,377 views

Published on

The exciting conclusion to our Haskell introduction. Today we talk about type classes, monads, a monadic parser combinators (e.g. Parsec) climaxing with an example JSON parser.

Published in: Technology, Art & Photos
5 Likes
Statistics
Notes
• Full Name
Comment goes here.

Are you sure you want to Yes No
• Be the first to comment

Views
Total views
1,377
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
58
0
Likes
5
Embeds 0
No embeds

No notes for slide

1. 1. HaskellA Whirlwind Tour (Part III) William Taysom ~ 2011
2. 2. Haskell is a non-strict,purely functionalprogramming languagewith strong,static type inference.
3. 3. Review
4. 4. Recursive Datadata Color = Red | Green | Blue | Mix Color Color
5. 5. Recursive Functionshue :: Color -> Maybe Doublehue Red = Just 0hue Green = Just 120hue Blue = Just 240
6. 6. 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
7. 7. Parametric Datadata (a, b) = (a, b)data Either a b = Left a | Right bdata Maybe a = Nothing | Just adata [a] = [] | a:[a]type String = [Char]
8. 8. Parametric Functions(.) :: (b -> c) -> (a -> b) -> a -> cinfixr . -- 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
9. 9. List ComprehensionsprimitivePythagoreanTriples = [ (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]
10. 10. Type Classes
11. 11. Membership Testinfix 4 `elem`x `elem` xs = case filter (== x) xs of [] -> False _ -> Trueq `elem` a_z --> True8 `elem` a_z --> False
12. 12. Membership Testelem :: a -> [a] -> Boolinfix 4 `elem`x `elem` xs = case filter (== x) xs of [] -> False _ -> Trueq `elem` a_z --> True8 `elem` a_z --> False
13. 13. Membership Testelem :: a -> [a] -> Boolinfix 4 `elem`x `elem` xs = case filter (== x) xs of [] -> False _ -> Trueq `elem` a_z --> True8 `elem` a_z --> False
14. 14. Membership Testelem :: a -> [a] -> Boolinfix 4 `elem`x `elem` xs = case filter (== x) xs of [] -> False _ -> Trueq `elem` a_z --> True8 `elem` a_z --> False
15. 15. Membership Testelem :: a -> [a] -> Boolinfix 4 `elem`x `elem` xs = case filter (== x) xs of [] -> False _ -> Trueq `elem` a_z --> True8 `elem` a_z --> False
16. 16. Membership Testelem :: a -> [a] -> Boolinfix 4 `elem`x `elem` xs = case filter (== x) xs of [] -> False (==) :: Eq a => a -> a -> Bool _ -> Trueq `elem` a_z --> True8 `elem` a_z --> False
17. 17. Membership Testelem :: a -> [a] -> Boolinfix 4 `elem`x `elem` xs = case filter (== x) xs of [] -> False (==) :: Eq a => a -> a -> Bool _ -> Trueq `elem` a_z --> True8 `elem` a_z --> False
18. 18. Membership Testelem :: a -> [a] -> Boolinfix 4 `elem`x `elem` xs = case filter (== x) xs of [] -> False _ -> Trueq `elem` a_z --> True8 `elem` a_z --> False
19. 19. Membership Testelem :: Eq a => a -> [a] -> Boolinfix 4 `elem`x `elem` xs = case filter (== x) xs of [] -> False _ -> Trueq `elem` a_z --> True8 `elem` a_z --> False
20. 20. Membership Testelem :: Eq a => a -> [a] -> Boolinfix 4 `elem`x `elem` xs = case filter (== x) xs of [] -> False _ -> Trueq `elem` a_z --> True8 `elem` a_z --> False
21. 21. Eq Instanceinstance Eq Color where Red == Red = True Green == Green = True Blue == Blue = True Mix c c == Mix d d = c == d && c == d _ == _ = False
22. 22. Eq Instanceinstance Eq Color where Red == Red = True Green == Green = True Blue == Blue = True Mix c c == Mix d d = c == d && c == d _ == _ = False
23. 23. Eq Instanceghci> :i Colorinstance Eq Color where Red == Red = True Green == Green = True Blue == Blue = True Mix c c == Mix d d = c == d && c == d _ == _ = False
24. 24. ghci> :i Colordata Color = Red | Green | Blue | MixColor Color ! Defined at example.hs:1:6-10 --instance Eq Color -- Defined atexample.hs:3:10-17ghci>
25. 25. ghci> :i Colordata Color = Red | Green | Blue | MixColor Color ! Defined at example.hs:1:6-10 --instance Eq Color -- Defined atexample.hs:3:10-17ghci> :i Eq
26. 26. Default Definitionsghci> :i Colordata Color = Red | Green | Blue | MixColor Color ! Eq a where example.hs:1:6-10 -- Defined at classinstance Eq Color -- Defined at (==), (/=) :: a -> a -> Boolexample.hs:3:10-17ghci> :i=Eq (x == y) x /= y notclass Eq=anot (x /= y) x == y where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool ! Defined in GHC.Classes --... followed by 26 instances ...
27. 27. Default Definitionsclass Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y) x == y = not (x /= y)
28. 28. Default Definitionsclass Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y) x == y = not (x /= y)
29. 29. Default Definitionsclass Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y) x == y = not (x /= y)
30. 30. Default Definitionsghci> :i Colordata Color = Red | Green | Blue | MixColor Color ! Eq a where example.hs:1:6-10 -- Defined at classinstance Eq Color -- Defined at (==), (/=) :: a -> a -> Boolexample.hs:3:10-17ghci> :i=Eq (x == y) x /= y notclass Eq=anot (x /= y) x == y where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool ! Defined in GHC.Classes --... followed by 26 instances ...
31. 31. ... some Eq instances ...instance Eq Colorinstance Eq Boolinstance Eq Char
32. 32. ... some Eq instances ...instance Eq Colorinstance Eq Boolinstance Eq Charinstance Eq a => Eq [a]instance (Eq a, Eq b) => Eq (a, b)
33. 33. ghci> :t compare
34. 34. ghci> :t comparecompare :: Ord a => a -> a -> Orderingghci>
35. 35. ghci> :t comparecompare :: Ord a => a -> a -> Orderingghci> :i Ord
36. 36. Ord Instanceghci> :t comparecompare :: Ord a => a -> a -> Orderingghci> :i Ordclass 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
37. 37. Ord Instanceinstance 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
38. 38. Ord Instanceinstance 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. 39. Derived Instancesdata Color = Red | Green | Blue | Mix Color Color deriving (Eq, Ord, Read, Show)
40. 40. Derived Instancesdata Color = Red | Green | Blue | Mix Color Color deriving (Eq, Ord, Read, Show)
41. 41. Derived Instancesghci> show (Mix Red Green)data Color = Red | Green | Blue | Mix Color Color deriving (Eq, Ord, Read, Show)
42. 42. ghci> show (Mix Red Green)"Mix Red Green"ghci>
43. 43. ghci> show (Mix Red Green)"Mix Red Green"ghci> read "Mix Red Green"
44. 44. ghci> show (Mix Red Green)"Mix Red Green"ghci> read "Mix Red Green"<interactive>:1:1: Ambiguous type variable `a0 in theconstraint: (Read a0) arising from a use of`read Probable fix: add a type signaturethat fixes these type variable(s) In the expression: read "Mix RedGreen" In an equation for `it: it = read"Mix Red Green"
45. 45. ghci> show (Mix Red Green)"Mix Red Green"ghci> read "Mix Red Green"<interactive>:1:1: Ambiguous type variable `a0 in theconstraint: (Read a0) arising from a use of`read Probable fix: add a type signaturethat fixes these type variable(s) In the expression: read "Mix RedGreen" In an equation for `it: it = read"Mix Red Green"
46. 46. ghci> show (Mix Red Green)"Mix Red Green"ghci> read "Mix Red Green"<interactive>:1:1: Ambiguous type variable `a0 in theconstraint: (Read a0) arising from a use of`read Probable fix: add a type signaturethat fixes these type variable(s) In the expression: read "Mix RedGreen" In an equation for `it: it = read"Mix Red Green"
54. 54. Type Classes Compared
55. 55. Type Classes Compared
56. 56. 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)
57. 57. 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)
58. 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. 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. 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. 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. 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. 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. 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. 65. intFromHexString :: String -> IntintFromHexString [] =0intFromHexString (c:cs) = digitToInt c * 16 ^ length cs + intFromHexString cs
66. 66. numberFromString :: Num a => String -> anumberFromString [] = 0numberFromString (c:cs) = fromIntegral (digitToInt c) * 10 ^ fromIntegral (length cs) + integerFromString cs
67. 67. numberFromString :: Num a => String -> anumberFromString [] = 0numberFromString (c:cs) = fromIntegral (digitToInt c) * 10 ^ fromIntegral (length cs) + integerFromString cs fromIntegral :: (Num b, Integral a) => a -> b
69. 69. Monad Classclass Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b m >> n = m >>= _ -> n
70. 70. Maybe (Failure)instance Monad Maybe where return = Just Nothing >>= k = Nothing Just x >>= k = k x
71. 71. 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
72. 72. hue (Mix c c) = case (hue c, hue c) of (Just h, Just h) -> ... _ -> Nothing
73. 73. hue (Mix c c) = case hue c of Just h -> case hue c of Just h -> ... Nothing -> Nothing Nothing -> Nothing
74. 74. hue (Mix c c) = case hue c of Just h -> hue c >>= h -> ... Nothing -> Nothing
75. 75. hue (Mix c c) = hue c >>= h -> hue c >>= h -> ...
76. 76. hue (Mix c c) = hue c >>= h -> do h <- hue c; ...
77. 77. hue (Mix c c) = do h <- hue c do h <- hue c; ...
78. 78. hue (Mix c c) = do h <- hue c h <- hue c ...
79. 79. 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
80. 80. 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
81. 81. List (Nondeterminism)instance Monad [] where return x = [x] xs >>= k = concat (map k xs)
82. 82. [ (a, b, c) | c <- nats, b <- [1..c], a <- [1..b]]
83. 83. [ (a, b, c) | c <- nats, b <- [1..c], a <- [1..b]]do c <- nats b <- [1..c] a <- [1..b] return (a, b, c)
84. 84. Generalized Map(<\$>) :: Monad m => (a -> b) -> m a -> m bf <\$> m = m >>= return . ford <\$> "abc" --> [97, 98, 99]
85. 85. Constant Map(<\$) :: Monad m => a -> m b -> m a(<\$) = (<\$>) . constx <\$ "abc" --> "xxx"
86. 86. [ (a, b, c) | c <- nats, b <- [1..c], a <- [1..b]]do c <- nats b <- [1..c] a <- [1..b] return (a, b, c)
87. 87. [ (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)
88. 88. MonadPlus Classclass Monad m => MonadPlus m where mzero :: m a mplus :: m a -> m a -> m a
89. 89. List (Nondeterminism)instance MonadPlus [] where mzero = [] mplus = (++)
90. 90. Guardguard :: MonadPlus m => Bool -> m ()guard True = return ()guard False = mzero
91. 91. Getterdata Getter a = Getter (String -> (a, String))get :: Getter a -> String -> (a, String)get (Getter g) = g
92. 92. Getterinstance Monad Getter where return x = Getter \$ s -> (x, s) g >>= k = Getter \$ s -> let (x, s) = get g s in get (k x) s
93. 93. Primitive ActiongetChar :: Getter ChargetChar = Getter \$ s -> case s of c:cs -> (c , cs) "" -> (0, "")
94. 94. Derived ActiongetLine :: Getter StringgetLine = do c <- getChar if c == n || c == 0 then return "" else do s <- getLine return \$ c:sget getLine "hellonworld" --> ("hello", "world")
95. 95. IOdata IO a = IO (RealWorld -> (a, RealWorld))putChar :: Char -> IO ()
96. 96. Print FunctionsputStr :: String -> IO ()putStr "" = return ()putStr (c:cs) = do putChar c putStr cs
97. 97. Print FunctionsputStrLn :: String -> IO ()putStrLn s = do putStr s putChar n
98. 98. Main Point“The business of the program is to construct onegianormous action which is then performed.” — Simon Peyton-Jones
99. 99. hello.hsmain = putStrLn "hello, world"
100. 100. Parsers
101. 101. Parsers
102. 102. Parsersdata Parser a = Parser (String -> [(a, String)])parse :: Parser a -> String -> [(a, String)]parse (Parser p) = p
103. 103. Parsersinstance Monad Parser where return x = Parser \$ s -> [(x, s)] p >>= k = Parser \$ s -> concat [parse (k x) s | (x, s) <- parse p s]
104. 104. Parsersinstance MonadPlus Parser where mzero = Parser \$ s -> [] mplus p q = Parser \$ s -> parse p s ++ parse q s
105. 105. Parsersinstance MonadPlus Parser where mzero = Parser \$ s -> [] mplus p q = Parser \$ s -> parse p s ++ parse q s(<|>) :: Parser a -> Parser a -> Parser ainfixr 1 <|>(<|>) = mplus
106. 106. Primitive ActionsanyChar :: Parser CharanyChar = Parser \$ s -> case s of c:cs -> [(c, cs)] "" -> []eof :: Parser ()eof = Parser \$ s -> case s of c:cs -> [] "" -> [((), "")]
107. 107. Derived Actionssatisfy :: (Char -> Bool) -> Parser Charsatisfy f = do c <- anyChar if f c then return c else mzero
108. 108. Derived Actionschar :: Char -> Parser Charchar c = satisfy (== c)
109. 109. Derived Actionsstring :: String -> Parser Stringstring "" = return ""string s@(c:cs) = do char c string cs return s
110. 110. BacktrackinghiHeHello = string "hi" <|> string "he" <|> string "hello"
111. 111. BacktrackinghiHeHello = string "hi" <|> string "he" <|> string "hello"parse hiHeHello "hello" --> [("he","llo"), ("hello","")]
112. 112. Parsectype Parser = Parsec String ()
113. 113. Parsectype Parser = Parsec String ()hiHeHello = string "hi" <|> string "he" <|> string "hello"parseTest hiHeHello "hello" >>-> unexpected "e" expecting "hi"
114. 114. Optional Backtrackingtry :: Parser a -> Parser a
115. 115. Optional Backtrackingtry :: Parser a -> Parser ahiHeHello = try (string "hi") <|> string "he" <|> string "hello"
116. 116. Optional Backtrackingtry :: Parser a -> Parser ahiHeHello = try (string "hi") <|> string "he" <|> string "hello"parseTest hiHeHello "hello" >>-> "he"
117. 117. Error Messages(<?>) :: Parser a -> String -> Parser a
118. 118. Error Messages(<?>) :: Parser a -> String -> Parser aspace :: Parser Charspace = satisfy isSpace <?> "space"digit :: Parser Chardigit = satisfy isDigit <?> "digit"hexDigit :: Parser CharhexDigit = satisfy isHexDigit <?> "hexadecimal digit"
119. 119. Error MessagesparseTest (space <|> digit <|> hexDigit) "hello" >>-> unexpected "h" expecting space, digit or hexadecimal digit
120. 120. Parser CombinatorsoneOf :: String -> Parser Char-- ExampleeE = oneOf "eE"
121. 121. Parser CombinatorsnoneOf :: String -> Parser Char-- ExamplenotDoubleQuote = noneOf """
122. 122. Parser Combinatorsbetween :: Parser a -> Parser b -> Parser c -> Parser c-- Definitionbetween open close p = do open x <- p close return x
123. 123. Parser Combinatorsoption :: a -> Parser a -> Parser a-- Definitionoption x p = p <|> return x
124. 124. Parser Combinatorscount :: Int -> Parser a -> Parser [a]-- ExamplehexDigit4 = count 4 hexDigit
125. 125. Parser Combinatorsmany, many1 :: Parser a -> Parser [a]-- Exampledigits = many1 digit
126. 126. Parser CombinatorsskipMany :: Parser a -> Parser ()-- ExampleskipMany p = many p >> return ()
127. 127. Parser Combinatorsspaces :: Parser ()-- Definitionspaces = skipMany space
128. 128. Parser CombinatorssepBy :: Parser a -> Parser b -> Parser [a]-- Examplewords = (many1 . satisfy) (not . isSpace) `sepBy` spaces
129. 129. Space ManagementjustOne :: Parser a -> Parser ajustOne = between spaces (spaces >> eof)
130. 130. Space Managementchar_sp :: Char -> Parser ()char_sp c = do char c spacessp_char_sp :: Char -> Parser ()sp_char_sp c = do spaces char_sp c
131. 131. Space ManagementcommaGroup :: Char -> Parser a -> Char -> Parser [a]commaGroup open item close = between (char_sp open) (sp_char_sp close) \$ item `sepBy` sp_char_sp ,
132. 132. Parse String
133. 133. Parse Stringjsstring :: Parser Stringjsstring = between doubleQuote doubleQuote \$ many character
134. 134. Parse Stringjsstring :: Parser Stringjsstring = between doubleQuote doubleQuote \$ many characterdoubleQuote :: Parser ChardoubleQuote = char "
135. 135. Parse Stringjsstring :: Parser Stringjsstring = between doubleQuote doubleQuote \$ many characterdoubleQuote :: Parser ChardoubleQuote = char "character :: Parser Charcharacter = (char >> escapeChar) <|> notDoubleQuote
136. 136. escapeChar :: Parser CharescapeChar = char " <|> char <|> char / <|> b <\$ char b <|> f <\$ char f <|> n <\$ char n <|> r <\$ char r <|> t <\$ char t <|> unicode
137. 137. unicode :: Parser Charunicode = do char u digits <- hexDigit4 let n = intFromHexString digits return \$ chr n
138. 138. Parse Number
139. 139. Parse Numbernumber :: Parser Doublenumber = do s <- sign n <- int f <- frac e <- expon return \$ s * (n + f) * e
140. 140. sign :: Parser Doublesign = option 1 \$ (-1) <\$ char -int :: Parser Doubleint = 0 <\$ char 0 <|> numberFromString <\$> digits
141. 141. frac :: Parser Doublefrac = option 0 \$ do char . n <- digits return \$ numberFromString n / 10 ^^ length nexpon :: Parser Doubleexpon = option 1 \$ do eE s <- sign n <- digits return \$ s * 10 ** numberFromString n
142. 142. Parse JSON
143. 143. Parse JSON
144. 144. Parse JSON
145. 145. Parse JSONdata Value = String String | Number Double | Object [(String, Value)] | Array [Value] | Bool Bool | Null
146. 146. Parse JSON value = String <\$>jsstring <|> Number <\$>number <|> Object <\$>commaGroup { pair } <|> Array <\$>commaGroup [ value ] <|> Bool True <\$ string "true" <|> Bool False <\$ string "false" <|> Null <\$ string "null"
147. 147. Parse JSONdata Value = String String | Number Double | Object [(String, Value)] | Array [Value] | Bool Bool | Null
148. 148. Parse JSON value = String <\$>jsstring <|> Number <\$>number <|> Object <\$>commaGroup { pair } <|> Array <\$>commaGroup [ value ] <|> Bool True <\$ string "true" <|> Bool False <\$ string "false" <|> Null <\$ string "null"
149. 149. pair :: Parser (String, Value)pair = do s <- jsstring sp_char_sp : v <- value spaces return (s, v)
150. 150. parseJSON :: String -> ValueparseJSON s = case parse (justOne value) "" s of Left err -> error \$ "JSON parse error " ++ show err Right v -> v
151. 151. parseJSON "{"just": ["some", 4, "u24E4"]}" --> Object [("just", Array [String "some", Number 4.0, String "9444"])]
152. 152. parseJSON "{"just": ["some", 4, "u24E4"]}" --> Object [("just", Array [String "some", Number 4.0, String "9444"])]parseJSON "{"just": ["some", 4 "u24E4"]}" >>-> *** Exception: JSON parse error (line 1, column 21): unexpected """ expecting space or ","
153. 153. Summary
154. 154. Summary
155. 155. Summary Parsers Monads Type Classes Parametric Types Functions and Data Types
156. 156. Summary Parsers Monads Type Classes Parametric Types Functions and Data Types
157. 157. Summary Parsers Monads Type Classes Parametric Types Functions and Data Types
158. 158. Summary Parsers Monads Type Classes Parametric Types Functions and Data Types
159. 159. Summary Parsers Monads Type Classes Parametric Types Functions and Data Types
160. 160. Haskell is a non-strict,purely functionalprogramming languagewith strong,static type inference.
161. 161. Thank You