Last active
June 14, 2018 20:14
-
-
Save rnagasam/41b65fa2af7f5c46f8e2b3b4f4760780 to your computer and use it in GitHub Desktop.
Solutions to Tony Morris's Haskell Exercises
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE InstanceSigs #-} | |
-- http://blog.tmorris.net/posts/20-intermediate-haskell-exercises/ | |
-- Functor | |
class Fluffy f where | |
furry :: (a -> b) -> f a -> f b | |
instance Fluffy [] where | |
furry :: (a -> b) -> [a] -> [b] | |
furry f = foldr ((:) . f) [] | |
instance Fluffy Maybe where | |
furry :: (a -> b) -> Maybe a -> Maybe b | |
furry f (Just x) = Just $ f x | |
furry _ _ = Nothing | |
instance Fluffy ((->) t) where | |
furry :: (a -> b) -> (t -> a) -> (t -> b) | |
furry = (.) | |
instance Fluffy (Either e) where | |
furry :: (a -> b) -> Either e a -> Either e b | |
furry f (Right v) = Right $ f v | |
furry _ (Left v) = Left v | |
newtype EitherLeft b a = EitherLeft (Either a b) deriving (Show) | |
newtype EitherRight a b = EitherRight (Either a b) deriving (Show) | |
instance Fluffy (EitherLeft t) where | |
furry :: (a -> b) -> EitherLeft t a -> EitherLeft t b | |
furry f (EitherLeft (Left val)) = EitherLeft . Left $ f val | |
furry _ (EitherLeft (Right val)) = EitherLeft . Right $ val | |
instance Fluffy (EitherRight t) where | |
furry :: (a -> b) -> EitherRight t a -> EitherRight t b | |
furry _ (EitherRight (Left val)) = EitherRight . Left $ val | |
furry f (EitherRight (Right val)) = EitherRight . Right $ f val | |
-- Monad | |
class Misty m where | |
banana :: (a -> m b) -> m a -> m b | |
unicorn :: a -> m a | |
furry' :: (a -> b) -> m a -> m b | |
furry' f = banana (unicorn . f) | |
instance Misty [] where | |
banana :: (a -> [b]) -> [a] -> [b] | |
banana = concatMap | |
unicorn :: a -> [a] | |
unicorn = (: []) | |
instance Misty Maybe where | |
banana :: (a -> Maybe b) -> Maybe a -> Maybe b | |
banana _ Nothing = Nothing | |
banana k (Just x) = k x | |
unicorn :: a -> Maybe a | |
unicorn = Just | |
instance Misty ((->) e) where | |
banana :: (a -> (e -> b)) -> (e -> a) -> (e -> b) | |
banana a2eb ea = \e -> a2eb (ea e) e | |
unicorn :: a -> (e -> a) | |
unicorn = const | |
instance Misty (EitherLeft t) where | |
banana :: (a -> EitherLeft t b) -> EitherLeft t a -> EitherLeft t b | |
banana mf (EitherLeft (Left a)) = mf a | |
banana _ (EitherLeft (Right a)) = EitherLeft . Right $ a | |
unicorn :: a -> EitherLeft t a | |
unicorn = EitherLeft . Left | |
instance Misty (EitherRight t) where | |
banana :: (a -> EitherRight t b) -> EitherRight t a -> EitherRight t b | |
banana mf (EitherRight (Right a)) = mf a | |
banana _ (EitherRight (Left a)) = EitherRight . Left $ a | |
unicorn :: a -> EitherRight t a | |
unicorn = EitherRight . Right | |
-- join | |
jellybean :: (Misty m) => m (m a) -> m a | |
jellybean = banana id | |
-- ap | |
-- ap v mk = v >>= (\x -> mk >>= (\f -> return $ f x)) | |
-- ap v mk = do { x <- v; f <- mk; return $ f x } | |
apple :: (Misty m) => m a -> m (a -> b) -> m b | |
apple v mk = banana (\x -> banana (\f -> unicorn $ f x) mk) v | |
-- mapM | |
moppy :: (Misty m) => [a] -> (a -> m b) -> m [b] | |
moppy xs k = sausage $ furry' k xs | |
-- sequence | |
-- sequence = foldr k (return []) | |
-- where k m m' = do {x <- m; xs <- m'; return (x:xs)} | |
-- or | |
-- sequence = foldr (liftM2 (:)) (return []) | |
sausage :: (Misty m) => [m a] -> m [a] | |
sausage = foldr (banana2 (:)) (unicorn []) | |
-- bonus : use apple + furry' | |
banana2 :: (Misty m) => (a -> b -> c) -> m a -> m b -> m c | |
banana2 f ma mb = apple mb $ furry' f ma | |
-- bonus : use apple + banana2 | |
banana3 :: (Misty m) => (a -> b -> c -> d) -> m a -> m b -> m c -> m d | |
banana3 f ma mb mc = apple mc $ banana2 f ma mb | |
-- bonus : use apple + banana3 | |
banana4 :: (Misty m) => (a -> b -> c -> d -> e) -> m a -> m b -> m c -> m d -> m e | |
banana4 f ma mb mc md = apple md $ banana3 f ma mb mc | |
newtype State s a = State { | |
state :: s -> (s, a) | |
} | |
instance Fluffy (State s) where | |
furry :: (a -> b) -> State s a -> State s b | |
furry f sa = State sb | |
where sb = \s -> let (s', a) = state sa s | |
in (s', f a) | |
instance Misty (State s) where | |
banana :: (a -> State s b) -> State s a -> State s b | |
banana k sa = State $ \s -> let (s', a) = state sa s | |
in state (k a) s' | |
unicorn :: a -> State s a | |
unicorn a = State $ \s -> (s,a) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment