parent
							
								
									da33ab0f18
								
							
						
					
					
						commit
						bc90acc41f
					
				
				 5 changed files with 133 additions and 0 deletions
			
			
		| @ -0,0 +1,2 @@ | |||||||
|  | # GOTCHA! Exercise time | ||||||
|  | see src/gotcha.hs | ||||||
| @ -0,0 +1,5 @@ | |||||||
|  | # Exercises: Compose Instances | ||||||
|  | see src/gotcha.hs | ||||||
|  | 
 | ||||||
|  | ## Bifunctor | ||||||
|  | see src/bifunctor.hs | ||||||
| @ -0,0 +1,20 @@ | |||||||
|  | {-# LANGUAGE InstanceSigs #-} | ||||||
|  | module IdentityT where | ||||||
|  | 
 | ||||||
|  | newtype IdentityT f a = IdentityT { runIdentityT :: f a } | ||||||
|  | 
 | ||||||
|  | instance Functor f => Functor (IdentityT f) where | ||||||
|  |     fmap f (IdentityT fa) = IdentityT $ fmap f fa | ||||||
|  | 
 | ||||||
|  | instance Applicative f => Applicative (IdentityT f) where | ||||||
|  |     pure a = IdentityT $ pure a | ||||||
|  | 
 | ||||||
|  |     (IdentityT ff) <*> (IdentityT fa) = | ||||||
|  |         IdentityT $ ff <*> fa | ||||||
|  | 
 | ||||||
|  | instance Monad m => Monad (IdentityT m) where | ||||||
|  |     return = pure | ||||||
|  | 
 | ||||||
|  |     (>>=) :: IdentityT m a -> (a -> IdentityT m b) -> IdentityT m b | ||||||
|  |     (IdentityT ma) >>= f = | ||||||
|  |         IdentityT $ ma >>= (runIdentityT . f) | ||||||
| @ -0,0 +1,40 @@ | |||||||
|  | {-# LANGUAGE InstanceSigs #-} | ||||||
|  | module BiFunctor where | ||||||
|  | 
 | ||||||
|  | import Data.Bifunctor | ||||||
|  | 
 | ||||||
|  | data Deux a b = Deux a b | ||||||
|  | instance Bifunctor Deux where | ||||||
|  |     bimap :: (a -> b) -> (c -> d) -> Deux a c -> Deux b d | ||||||
|  |     bimap f g (Deux a b) = Deux (f a) (g b) | ||||||
|  | 
 | ||||||
|  | data Const a b = Const a | ||||||
|  | instance Bifunctor Const where | ||||||
|  |     bimap f _ (Const a) = Const (f a) | ||||||
|  | 
 | ||||||
|  | data Drei a b c = Drei a b c | ||||||
|  | instance Bifunctor (Drei a) where | ||||||
|  |     bimap f g (Drei a b c) = Drei a (f b) (g c) | ||||||
|  | 
 | ||||||
|  | data SuperDrei a b c = SuperDrei a b | ||||||
|  | instance Bifunctor (SuperDrei a) where | ||||||
|  |     bimap f _ (SuperDrei a b) = SuperDrei a (f b) | ||||||
|  | 
 | ||||||
|  | data SemiDrei a b c = SemiDrei a | ||||||
|  | instance Bifunctor (SemiDrei a) where | ||||||
|  |     bimap _ _ (SemiDrei a) = SemiDrei a | ||||||
|  | 
 | ||||||
|  | data Quadriceps a b c d = Quadzzz a b c d | ||||||
|  | instance Bifunctor (Quadriceps a b) where | ||||||
|  |     bimap f g (Quadzzz a b c d) = Quadzzz a b (f c) (g d) | ||||||
|  | 
 | ||||||
|  | data Either' a b = Left' a | Right' b | ||||||
|  | instance Bifunctor Either' where | ||||||
|  |     bimap f _ (Left' a) = Left' (f a) | ||||||
|  |     bimap _ g (Right' b) = Right' (g b) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,66 @@ | |||||||
|  | {-# LANGUAGE InstanceSigs #-} | ||||||
|  | module Gotcha where | ||||||
|  | 
 | ||||||
|  | newtype Identity a = Identity { runIdentity :: a } | ||||||
|  | 
 | ||||||
|  | instance Functor Identity where | ||||||
|  |     fmap f (Identity a) = Identity $ f a | ||||||
|  | 
 | ||||||
|  | instance Applicative Identity where | ||||||
|  |     pure = Identity | ||||||
|  |     (Identity f) <*> (Identity a) = Identity (f a) | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | newtype Compose f g a = Compose { getCompose :: f (g a) } deriving (Eq, Show) | ||||||
|  | 
 | ||||||
|  | instance (Functor f, Functor g) => Functor (Compose f g) where | ||||||
|  |     fmap f (Compose fga) = Compose $ (fmap . fmap) f fga | ||||||
|  | 
 | ||||||
|  | instance (Applicative f, Applicative g) => Applicative (Compose f g) where | ||||||
|  |     pure :: a -> Compose f g a | ||||||
|  |     pure a = Compose $ pure (pure a) | ||||||
|  |     -- The next one took me a while. I find the following usefull in | ||||||
|  |     -- understanding the solution. Ignoring the Compose part of it we | ||||||
|  |     -- have a type signature of: | ||||||
|  |     -- :: f (g (a -> b)) -> f (g a) -> f (g b) | ||||||
|  |     -- In the applicative the following would be easy: | ||||||
|  |     -- :: f (g a -> g b) -> f (g a) -> f (g b) | ||||||
|  |     -- as that would just (<*>), if we somehow find a way to go from | ||||||
|  |     -- :: f (g (a -> b)) to (f (g a -> g b)) using applicative and/or functor | ||||||
|  |     -- functions we would be set. | ||||||
|  |     -- If you ignore the f part of it,  you see we have: | ||||||
|  |     -- :: g (a -> b) -> g a -> g b which is nothing but (<*>) | ||||||
|  |     -- We can also see this as: | ||||||
|  |     -- :: g (a -> b) -> (g a -> g b) | ||||||
|  |     -- In other words this is a function that returns another function where | ||||||
|  |     -- we know that the first argument/function is embeded in an f. We can use | ||||||
|  |     -- the fact that f is a functor to actually apply the function: | ||||||
|  |     -- :: fmap (g (a -> b) -> (g a -> g b)) (f (g (a -> b))) :: f (g a -> g b) | ||||||
|  |     -- Which brings us to: | ||||||
|  |     -- :: (<*>) f a = (fmap (<*>) f) <*> a | ||||||
|  |     (<*>) :: Compose f g (a -> b) -> Compose f g a -> Compose f g b | ||||||
|  |     (Compose h) <*> (Compose c) = Compose $  | ||||||
|  |         (fmap (<*>) h) <*> c | ||||||
|  | 
 | ||||||
|  | instance (Foldable f, Foldable g) => Foldable (Compose f g) where | ||||||
|  |     foldMap :: (Monoid m) => (a -> m) -> Compose f g a -> m | ||||||
|  |     foldMap f (Compose fga) = (foldMap . foldMap) f fga | ||||||
|  | 
 | ||||||
|  | -- foldMap :: (Monoid m, Foldable t) => (a -> m) -> (t a -> m) | ||||||
|  | -- (.) :: (b -> c) -> (a -> b) -> a -> c | ||||||
|  | -- Foldmap for f :: (g a -> m) -> f (g a) -> m | ||||||
|  | -- FoldMap for g :: (a -> m) -> g a -> m | ||||||
|  | -- (foldMap . foldMap) :: (a -> m) -> f (g a) -> m | ||||||
|  | 
 | ||||||
|  | instance (Traversable f, Traversable g) => Traversable (Compose f g) where | ||||||
|  |     traverse :: Applicative f' => (a -> f' b) -> Compose f g a  | ||||||
|  |                                             -> f' (Compose f g b) | ||||||
|  |     traverse f (Compose fga) = Compose <$> ((traverse . traverse) f fga) | ||||||
|  | 
 | ||||||
|  | -- traverse :: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b) | ||||||
|  | -- traverse for f :: ((g a) -> f' (g b)) -> f (g a) -> f' (f (g b)) | ||||||
|  | -- traverse for g :: (a -> f' b) -> g a -> f' (g b) | ||||||
|  | -- (traverse . traverse) :: (a -> f' b) -> f (g a) -> f' (f g b) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
					Loading…
					
					
				
		Reference in new issue