git.iko.soy/Haskell-HSE/haskell-lectures-2024
on main help sign in
187 lines 4.2 kB history raw
1# Useful Monad examples
3```haskell
4import Control.Applicative (Alternative (..), liftA2)
5import Control.Monad (ap)
6```
8```haskell ignore
9data Maybe a = Nothing | Just a deriving (Functor)
11instance Applicative Maybe where
12 pure :: a -> Maybe a
13 pure = Just
15 (<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
16 (<*>) = ap
18instance Monad Maybe where
19 (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
20 Just x >>= f = f x
21 Nothing >>= _ = Nothing
23-- return x >>= f = f x
24-- m >>= return = m
25-- (m >>= f) >>= g = m >>= (\x -> f x >>= g)
26```
28```haskell
29safeDiv :: (Fractional a, Eq a) => a -> a -> Maybe a
30safeDiv x y
31 | y == 0 = Nothing
32 | otherwise = Just (x / y)
33```
35```haskell ignore
36data Either e a = Left e | Right a deriving (Functor)
38instance Applicative
39 ...
41instance Monad where
42 Left err >>= f = Left err
43 Right ok >>= f = f ok
44```
46__Exercise__: either with accumulating errors
48```
49withOracle1 :: e -> a -> b
50withOracle2 :: e -> c -> d
52unified :: e -> (b -> c) -> a -> d
53unified ext f x = withOracle2 ext (f (withOracle1 ext x))
54```
56```haskell ignore
57instance Functor (e ->) where
58 fmap = liftA
60instance Applicative (e ->) where
61 pure :: a -> e -> a
62 pure = const
64 (<*>) = ap
66instance Monad (e ->) where
67 (>>=) :: (e -> a) -> (a -> e -> b) -> e -> b
68 (>>=) f g ext = g (f ext) ext
69```
71```haskell
72newtype Writer w a = Writer { runWriter :: (a, w) }
74instance Functor (Writer w) where
75 fmap :: (a -> b) -> Writer w a -> Writer w b
76 fmap f = Writer . (\(x, w) -> (f x, w)) . runWriter
78instance Monoid w => Applicative (Writer w) where
79 pure :: a -> Writer w a
80 pure = Writer . (\x -> (x, mempty))
82 (<*>) :: Writer w (a -> b) -> Writer w a -> Writer w b
83 (<*>) = ap
85instance Monoid w => Monad (Writer w) where
86 (>>=) :: Writer w a -> (a -> Writer w b) -> Writer w b
87 Writer (x, w) >>= f =
88 let Writer (y, w') = f x
89 in Writer (y, w <> w')
90```
92```haskell
93newtype State s a = State { runState :: s -> (a, s) }
94 deriving (Functor)
96instance Applicative (State s) where
97 pure :: a -> State s a
98 pure x = State $ \s -> (x, s)
100 (<*>) = ap
102instance Monad (State s) where
103 (>>=) :: State s a -> (a -> State s b) -> State s b
104 State x >>= f = State $ \s ->
105 let (xa, s') = x s
106 State y = f xa
107 in y s'
108```
110# Parsing
112```haskell
113newtype ParseError = ParseError { reason :: String }
115parseInt :: String -> Either ParseError (Int, String)
116parseInt = undefined
117-- parseInt "hello" -- error: gibberish
118-- parseInt "123" -- ok: (123, "")
119-- parseInt "hello123" -- error: gibberish
120-- parseInt "123hello" -- ok: (123, "hello")
121```
123```haskell
124newtype Parser a = Parser {
125 runParser :: String -> Either ParseError (a, String) }
126 deriving (Functor)
128instance Applicative Parser where
129 pure x = Parser $ \s -> Right (x, s)
130 (<*>) = ap
132instance Monad Parser where
133 (>>=) :: Parser a -> (a -> Parser b) -> Parser b
134 (>>=) = undefined -- TODO: finish instance
135```
137```haskell
138parsePair :: Parser a -> Parser b -> Parser (a, b)
139parsePair = liftA2 (,)
141parseEither ::
142 Parser Bool ->
143 Parser a ->
144 Parser b ->
145 Parser (Either a b)
146parseEither pb px py = do
147 b <- pb
148 if b then Left <$> px else Right <$> py
150peek :: Parser Char
151peek = Parser $ \xs -> case xs of
152 [] -> Left $ ParseError "empty"
153 (x : xs) -> Right (x, x : xs)
155take :: Parser ()
156take = Parser $ \xs -> case xs of
157 [] -> Left $ ParseError "empty"
158 (x : xs) -> Right ((), xs)
160eof :: Parser ()
161eof = Parser $ \xs -> case xs of
162 [] -> Right ((), xs)
163 (x : xs) -> Left $ ParseError "not empty"
165takeWhile :: (Char -> Bool) -> Parser String
166takeWhile = undefined -- TODO: write this out
167```
169What about expressions? Like $1 + (2 * 4) + 5 * 6 - 8$?
171```haskell ignore
172class Applicative f => Alternative f where
173 (<|>) :: f a -> f a -> f a
174 -- (a <|> b) <|> c = a <|> (b <|> c)
175 empty :: f a
176 -- unit relative to (<|>):
177 -- empty <|> a = a
178 -- a <|> empty = a
179```
181```haskell
182instance Alternative Parser where
183 (<|>) :: Parser a -> Parser a -> Parser a
184 (<|>) = error "TODO" -- TODO: finish
185 empty :: Parser a
186 empty = error "TODO"
187```