This IHaskell notebook contains my solutions to 20 intermediate exercies by Dan Burton.
David Banas capn.freako@gmail.com
Created: December 25, 2015
Fill in the blanks (which are marked error "todo") with a nontrivial implementation that typechecks. I recommend that you use the run button after implementing each one to make sure that it still typechecks. Let the types guide you! If you have trouble implementing a typeclass method, then try writing out the specialized type that it should have. For example, furry imlpemented for [] should have the type (a -> b) -> [a] -> [b].
In [1]:
import Data.Time
putStrLn "Notebook last run:"
getCurrentTime
In [2]:
class Fluffy f where
furry :: (a -> b) -> f a -> f b
-- Exercise 1
-- Relative Difficulty: 1
instance Fluffy [] where
furry = map
-- Exercise 2
-- Relative Difficulty: 1
instance Fluffy Maybe where
furry = fmap
-- Exercise 3
-- Relative Difficulty: 5
instance Fluffy ((->) t) where
-- furry :: (a -> b) -> (c -> a) -> (c -> b)
-- furry g h = g . h
furry = (.)
newtype EitherLeft b a = EitherLeft (Either a b)
newtype EitherRight a b = EitherRight (Either a b)
-- Exercise 4
-- Relative Difficulty: 5
instance Fluffy (EitherLeft t) where
-- furry :: (t -> u) -> EitherLeft t v -> EitherLeft u v
furry g (EitherLeft (Left x)) = EitherLeft (Left (g x))
furry g (EitherLeft (Right y)) = EitherLeft (Right y)
-- Exercise 5
-- Relative Difficulty: 5
instance Fluffy (EitherRight t) where
furry g (EitherRight (Left x)) = EitherRight (Left x)
furry g (EitherRight (Right y)) = EitherRight (Right (g y))
In [3]:
class Misty m where
banana :: (a -> m b) -> m a -> m b
unicorn :: a -> m a
-- Exercise 7
-- Relative Difficulty: 2
instance Misty [] where
-- banana :: (a -> [b]) -> [a] -> [b]
-- banana g xs = concat $ map g xs
-- banana g = concat . (map g)
banana = \ g -> concat . (map g)
-- unicorn :: a -> [a]
-- unicorn x = [x]
unicorn = (: [])
-- Exercise 8
-- Relative Difficulty: 2
instance Misty Maybe where
-- banana :: (a -> Maybe b) -> Maybe a -> Maybe b
banana g Nothing = Nothing
banana g (Just x) = g x
-- banana = \ g -> join . (fmap g) ?
-- unicorn :: a -> Maybe a
-- unicorn x = Just x
unicorn = Just
-- Exercise 9
-- Relative Difficulty: 6
instance Misty ((->) t) where
-- banana :: (a -> (t -> b)) -> (t -> a) -> (t -> b)
banana g h = \ x -> g (h x) x
-- unicorn :: a -> (t -> a)
-- unicorn x = const x
unicorn = const
newtype EitherLeft b a = EitherLeft (Either a b)
newtype EitherRight a b = EitherRight (Either a b)
-- Exercise 10
-- Relative Difficulty: 6
instance Misty (EitherLeft t) where
-- banana :: (a -> EitherLeft t b) -> EitherLeft t a -> EitherLeft t b
banana g (EitherLeft (Left a)) = g a
banana _ (EitherLeft (Right t)) = EitherLeft (Right t)
-- unicorn :: a -> EitherLeft t a
unicorn x = EitherLeft (Left x)
-- Exercise 11
-- Relative Difficulty: 6
instance Misty (EitherRight t) where
-- banana :: (a -> EitherRight t b) -> EitherRight t a -> EitherRight t b
banana g (EitherRight (Right a)) = g a
banana _ (EitherRight (Left t)) = EitherRight (Left t)
-- unicorn :: a -> EitherLeft t a
unicorn x = EitherRight (Right x)
In [4]:
-- Exercise 6
-- Relative Difficulty: 3
-- (use banana and/or unicorn)
furry' :: (Misty m) => (a -> b) -> m a -> m b
-- furry' g m = banana (unicorn . g) m
furry' g = banana (unicorn . g)
-- Exercise 12
-- Relative Difficulty: 3
jellybean :: (Misty m) => m (m a) -> m a
-- jellybean mm = banana id mm
jellybean = banana id
-- Exercise 13
-- Relative Difficulty: 6
apple :: (Misty m) => m a -> m (a -> b) -> m b
-- apple mx mf = banana (\x -> banana (\g -> unicorn (g x)) mf) mx
-- apple mx = \mf -> banana (\x -> banana (\g -> unicorn (g x)) mf) mx
apple = flip (\mf -> banana (\x -> banana (\g -> unicorn (g x)) mf))
-- Exercise 14
-- Relative Difficulty: 6
moppy :: (Misty m) => [a] -> (a -> m b) -> m [b]
-- moppy xs g = foldl (\m x -> banana (\ys -> (banana (\y -> unicorn (ys ++ [y])) (g x))) m) (unicorn []) xs
moppy = flip moppy'
where moppy' g = foldl (\m x -> banana (\ys -> (banana (\y -> unicorn (ys ++ [y])) (g x))) m) (unicorn [])
-- Exercise 15
-- Relative Difficulty: 6
-- (bonus: use moppy)
sausage :: (Misty m) => [m a] -> m [a]
-- sausage ms = moppy ms id
sausage = flip moppy id
-- Exercise 16
-- Relative Difficulty: 6
-- (bonus: use apple + furry')
banana2 :: (Misty m) => (a -> b -> c) -> m a -> m b -> m c
-- banana2 g ma mb = apple mb (furry' g ma)
-- banana2 g ma = flip apple (furry' g ma)
banana2 g = flip apple . furry' g
-- Exercise 17
-- Relative Difficulty: 6
-- (bonus: use apple + banana2)
banana3 :: (Misty m) => (a -> b -> c -> d) -> m a -> m b -> m c -> m d
banana3 g ma = flip apple . banana2 g ma
-- Exercise 18
-- Relative Difficulty: 6
-- (bonus: use apple + banana3)
banana4 :: (Misty m) => (a -> b -> c -> d -> e) -> m a -> m b -> m c -> m d -> m e
banana4 g ma mb = flip apple . banana3 g ma mb
In [5]:
newtype State s a = State {
state :: (s -> (s, a))
}
-- Exercise 19
-- Relative Difficulty: 9
instance Fluffy (State s) where
-- furry :: (a -> b) -> State s a -> State s b
furry g (State h) = State (second g . h)
second :: (b -> c) -> (a, b) -> (a, c)
second g p = (fst p, g . snd $ p)
-- Exercise 20
-- Relative Difficulty: 10
instance Misty (State s) where
-- banana :: (a -> State s b) -> State s a -> State s b
-- state sa :: s -> (s, a)
-- state . g . snd :: (a2, a1) -> s -> (s, a)
-- furry (state . g . snd) (state sa) :: a1 -> s -> (s, a)
-- jellybean (furry (state . g . snd) (state sa)) :: s -> (s, a)
banana g sa = State (jellybean (furry (state . g . snd) (state sa)))
-- unicorn :: a -> State s a
unicorn x = State (\s -> (s, x))