parent
ae7d8db3db
commit
285f44274c
10 changed files with 301 additions and 0 deletions
@ -0,0 +1,2 @@ |
||||
# Exercises: Instances of Func |
||||
see src/func.hs |
@ -0,0 +1,13 @@ |
||||
# Chapter 16 |
||||
## Maybe |
||||
### Exercise: Possibly |
||||
see src/Possibly.hs |
||||
|
||||
## Either |
||||
### Short Exercise |
||||
### Exercise 1 |
||||
see src/Sum.hs |
||||
|
||||
### Excercise 2 |
||||
Functor expects a type with kind `* -> *`. `Sum` and `Either` are of kind `* -> * -> *` In order to reduce it to `* -> *` we need to apply one type of kind `*`, but the only one we can apply right now is the first in the list. |
||||
|
@ -0,0 +1,13 @@ |
||||
# Chapter Excercises |
||||
## Can a valid Functor be written? |
||||
1. No, Bool is of kind `*` |
||||
2. Yes, see src/chptexc.hs |
||||
3. Yes, see src/chptexc.hs |
||||
4. The first f in `outF :: f (Mu f)` implies that f is of kind `* -> *`. `Mu` takes this f to return a type, so it's kind is `(* -> *) -> *`. This means we can't make a Functor from this as this is not `* -> *` |
||||
5. No, D is of kind `*` |
||||
|
||||
## Rearrange |
||||
see src/chptexc.hs |
||||
|
||||
## Write |
||||
see src/chptexc.hs |
@ -0,0 +1,4 @@ |
||||
# Excercises: Be Kind |
||||
1. `a` is of kind `*` |
||||
2. `b` is of kind `* -> *`, `T` has kind `* -> *` |
||||
3. `c` is of kinde `* -> * -> *` |
@ -0,0 +1,13 @@ |
||||
# Exercises: Heavy Lifting |
||||
1. `a = fmap (+1) $ read "[1]" :: [Int]` |
||||
2. `b = (fmap . fmap) (++ "lol") (Just ["Hi,", "Hello"])` |
||||
3. `c = fmap (*2) (\x -> x - 2)` |
||||
4. `d = fmap ((return '1' ++) . show) (\x -> [x,1..3])` |
||||
5. see block below |
||||
|
||||
``` |
||||
e :: IO Integer |
||||
e = let ioi = readIO "1" :: IO Integer |
||||
changed = fmap read (fmap (("123"++) . show) ioi) |
||||
in fmap (*3) changed |
||||
``` |
@ -0,0 +1,20 @@ |
||||
# Wait, how does that even typecheck |
||||
|
||||
``` |
||||
(.) :: (b -> c) -> (a -> b) -> a -> c |
||||
-- fmap fmap |
||||
fmap :: Functor f => (m -> n) -> f m -> f n |
||||
fmap :: Functor g => (x -> y) -> g x -> g y |
||||
``` |
||||
Let's typecheck `fmap . fmap.`. |
||||
|
||||
1. First, it's important to note that `fmap` is a function that takes a function `m -> n` and returns a function `f m -> f n`. |
||||
2. Using that information we see that `a` is actually `m -> n`. |
||||
3. We also see that `b` is actually `f m -> f n` **and** `x -> y`, so `x` has to be `f m` and `y` has to be `f n`. |
||||
4. We can then also conclude that `g x` is `g (f m)` and `g y` is `g (f n)` |
||||
|
||||
Armed with this knowledge, we can apply fmap to (.) a first time |
||||
`(fmap.) :: (Functor g) => (a -> (f m -> f n)) -> a -> g (f m) -> g (f n)` |
||||
|
||||
And now we apply it a second time: |
||||
`(fmap . fmap) :: (Functor g, Functor f) => (m -> n) -> g (f m) -> g (f n)` |
@ -0,0 +1,7 @@ |
||||
module Possibly where |
||||
|
||||
data Possibly a = LolNope | Yeppers a deriving (Eq, Show) |
||||
|
||||
instance Functor Possibly where |
||||
fmap _ LolNope = LolNope |
||||
fmap f (Yeppers a) = Yeppers $ f a |
@ -0,0 +1,7 @@ |
||||
module Sum where |
||||
|
||||
data Sum a b = First a | Second b deriving (Eq, Show) |
||||
|
||||
instance Functor (Sum a) where |
||||
fmap f (Second b) = Second $ f b |
||||
fmap _ a = a |
@ -0,0 +1,81 @@ |
||||
{-# LANGUAGE FlexibleInstances #-} |
||||
module ChptExc where |
||||
|
||||
data BoolAndSomethingElse a = False' a | True' a deriving (Eq, Show) |
||||
instance Functor BoolAndSomethingElse where |
||||
fmap f (False' a) = False' (f a) |
||||
fmap f (True' a) = True' (f a) |
||||
|
||||
data BoolAndMaybeSomethingElse a = Falsish | Truish a deriving (Eq, Show) |
||||
instance Functor BoolAndMaybeSomethingElse where |
||||
fmap f (Truish a) = Truish (f a) |
||||
fmap _ Falsish = Falsish |
||||
|
||||
-- Rearrange |
||||
data Sum a b = First a | Second b |
||||
instance Functor (Sum e) where |
||||
fmap _ (First a) = First a |
||||
fmap f (Second b) = Second (f b) |
||||
|
||||
data Company a b c = DeepBlue a c | Something b |
||||
instance Functor (Company e e') where |
||||
fmap _ (Something b) = Something b |
||||
fmap f (DeepBlue a c) = DeepBlue a (f c) |
||||
|
||||
data More a b = L a b a | R b a b deriving (Eq, Show) |
||||
instance Functor (More a) where |
||||
fmap f (L a b a') = L a (f b) a' |
||||
fmap f (R b a b') = R (f b) a (f b') |
||||
|
||||
-- Write |
||||
data Quant a b = Finance | Desk a | Bloor b |
||||
instance Functor (Quant a) where |
||||
fmap f (Bloor b) = Bloor (f b) |
||||
fmap _ Finance = Finance |
||||
fmap _ (Desk a) = Desk a |
||||
|
||||
data K a b = K a |
||||
instance Functor (K a) where |
||||
fmap _ (K a) = K a |
||||
|
||||
newtype Flip f a b = Flip (f b a) deriving (Eq, Show) |
||||
instance Functor (Flip K a) where |
||||
fmap f (Flip (K a)) = Flip $ K (f a) |
||||
|
||||
data EvilGoateeConst a b = GoatyConst b |
||||
instance Functor (EvilGoateeConst a) where |
||||
fmap f (GoatyConst b) = GoatyConst (f b) |
||||
|
||||
data LiftItOut f a = LiftItOut (f a) |
||||
instance Functor f => Functor (LiftItOut f) where |
||||
fmap f (LiftItOut fa) = LiftItOut $ fmap f fa |
||||
|
||||
data Parappa f g a = DaWrappa (f a) (g a) |
||||
instance (Functor f, Functor g) => Functor (Parappa f g) where |
||||
fmap f (DaWrappa fa ga) = DaWrappa (fmap f fa) (fmap f ga) |
||||
|
||||
data IgnoreOne f g a b = IgnoringSomething (f a) (g b) |
||||
instance (Functor f, Functor g) => Functor (IgnoreOne f g a) where |
||||
fmap f (IgnoringSomething fa ga) = IgnoringSomething fa (fmap f ga) |
||||
|
||||
data Notorious g o a t = Notorious (g o) (g a) (g t) |
||||
instance (Functor g) => Functor (Notorious g o a) where |
||||
fmap f (Notorious go ga gt) = Notorious go ga (fmap f gt) |
||||
|
||||
data List a = Nil | Cons a (List a) |
||||
instance Functor List where |
||||
fmap _ Nil = Nil |
||||
fmap f (Cons a l) = Cons (f a) (fmap f l) |
||||
|
||||
data GoatLord a = NoGoat | OneGoat a | |
||||
MoreGoats (GoatLord a) (GoatLord a) (GoatLord a) |
||||
instance Functor GoatLord where |
||||
fmap _ NoGoat = NoGoat |
||||
fmap f (OneGoat a) = OneGoat (f a) |
||||
fmap f (MoreGoats a b c) = MoreGoats (fmap f a) (fmap f b) (fmap f c) |
||||
|
||||
data TalkToMe a = Halt | Print String a | Read (String -> a) |
||||
instance Functor TalkToMe where |
||||
fmap _ Halt = Halt |
||||
fmap f (Print s a) = Print s (f a) |
||||
fmap f (Read a) = Read (fmap f a) |
@ -0,0 +1,141 @@ |
||||
module Func where |
||||
|
||||
import Test.QuickCheck |
||||
import Test.QuickCheck.Function |
||||
|
||||
functorIdentity :: (Functor f, Eq (f a)) => f a -> Bool |
||||
functorIdentity f = fmap id f == f |
||||
|
||||
functorCompose :: (Eq (f c), Functor f) => (a -> b) -> (b -> c) -> f a -> Bool |
||||
functorCompose f g x = (fmap g (fmap f x)) == (fmap (g . f) x) |
||||
|
||||
functorCompose' :: (Eq (f c), Functor f) => f a -> Fun a b -> Fun b c -> Bool |
||||
functorCompose' x (Fun _ f) (Fun _ g) = |
||||
(fmap (g . f) x) == (fmap g . fmap f $ x) |
||||
|
||||
-- 1 |
||||
newtype Identity a = Identity a deriving (Eq, Show) |
||||
instance Functor Identity where |
||||
fmap f (Identity a) = Identity (f a) |
||||
instance Arbitrary a => Arbitrary (Identity a) where |
||||
arbitrary = do |
||||
a <- arbitrary |
||||
return $ Identity a |
||||
type IdentId = Identity Int -> Bool |
||||
type IdentComp = Identity Int -> Fun Int String -> Fun String Float -> Bool |
||||
|
||||
-- 2 |
||||
data Pair a = Pair a a deriving (Eq, Show) |
||||
instance Functor Pair where |
||||
fmap f (Pair a a') = Pair (f a) (f a') |
||||
instance Arbitrary a => Arbitrary (Pair a) where |
||||
arbitrary = do |
||||
a <- arbitrary |
||||
a' <- arbitrary |
||||
return $ Pair a a' |
||||
type PairId = Pair Int -> Bool |
||||
type PairComp = Pair Int -> Fun Int String -> Fun String Float -> Bool |
||||
|
||||
-- 3 |
||||
data Two a b = Two a b deriving (Eq, Show) |
||||
instance Functor (Two a) where |
||||
fmap f (Two a b) = Two a (f b) |
||||
instance (Arbitrary a, Arbitrary b) => Arbitrary (Two a b) where |
||||
arbitrary = do |
||||
a <- arbitrary |
||||
b <- arbitrary |
||||
return $ Two a b |
||||
type TwoId = Two Int String -> Bool |
||||
type TwoComp = Two Int String -> Fun String Int -> Fun Int Float -> Bool |
||||
|
||||
-- 4 |
||||
data Three a b c = Three a b c deriving (Eq, Show) |
||||
instance Functor (Three a b) where |
||||
fmap f (Three a b c) = Three a b (f c) |
||||
instance (Arbitrary a, Arbitrary b, Arbitrary c) |
||||
=> Arbitrary (Three a b c) where |
||||
arbitrary = do |
||||
a <- arbitrary |
||||
b <- arbitrary |
||||
c <- arbitrary |
||||
return $ Three a b c |
||||
type ThreeId = Three Int String Float -> Bool |
||||
type ThreeComp = Three Int String Float -> |
||||
Fun Float String -> |
||||
Fun String Int -> |
||||
Bool |
||||
|
||||
-- 5 |
||||
data Three' a b = Three' a b b deriving (Eq, Show) |
||||
instance Functor (Three' a) where |
||||
fmap f (Three' a b b') = Three' a (f b) (f b') |
||||
instance (Arbitrary a, Arbitrary b) => Arbitrary (Three' a b) where |
||||
arbitrary = do |
||||
a <- arbitrary |
||||
b <- arbitrary |
||||
b' <- arbitrary |
||||
return $ Three' a b b' |
||||
type Three'Id = Three' Int String -> Bool |
||||
type Three'Comp = Three' Int String -> |
||||
Fun String Float -> |
||||
Fun Float Int -> |
||||
Bool |
||||
|
||||
-- 6 |
||||
data Four a b c d = Four a b c d deriving (Eq, Show) |
||||
instance Functor (Four a b c) where |
||||
fmap f (Four a b c d) = Four a b c (f d) |
||||
instance (Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d) |
||||
=> Arbitrary (Four a b c d) where |
||||
arbitrary = do |
||||
a <- arbitrary |
||||
b <- arbitrary |
||||
c <- arbitrary |
||||
d <- arbitrary |
||||
return $ Four a b c d |
||||
type FourId = Four Int String Float Ordering -> Bool |
||||
type FourComp = Four Int String Float Ordering -> |
||||
Fun Ordering Int -> |
||||
Fun Int String -> |
||||
Bool |
||||
|
||||
-- 7 |
||||
data Four' a b = Four' a a a b deriving (Eq, Show) |
||||
instance Functor (Four' a) where |
||||
fmap f (Four' a a' a'' b) = Four' a a' a'' (f b) |
||||
instance (Arbitrary a, Arbitrary b) => Arbitrary (Four' a b) where |
||||
arbitrary = do |
||||
a <- arbitrary |
||||
a' <- arbitrary |
||||
a'' <- arbitrary |
||||
b <- arbitrary |
||||
return $ Four' a a' a'' b |
||||
type Four'Id = Four' Int String -> Bool |
||||
type Four'Comp = Four' Int String -> |
||||
Fun String Bool -> |
||||
Fun Bool Float -> |
||||
Bool |
||||
|
||||
-- 8 |
||||
-- This is not possible because Trivial is of kind * |
||||
-- And you need * -> *. |
||||
|
||||
main :: IO () |
||||
main = do |
||||
putStrLn "Functor Identity Tests" |
||||
quickCheck (functorIdentity :: IdentId) |
||||
quickCheck (functorIdentity :: PairId) |
||||
quickCheck (functorIdentity :: TwoId) |
||||
quickCheck (functorIdentity :: ThreeId) |
||||
quickCheck (functorIdentity :: Three'Id) |
||||
quickCheck (functorIdentity :: FourId) |
||||
quickCheck (functorIdentity :: Four'Id) |
||||
|
||||
putStrLn "Functor Composition Tests" |
||||
quickCheck (functorCompose' :: IdentComp) |
||||
quickCheck (functorCompose' :: PairComp) |
||||
quickCheck (functorCompose' :: TwoComp) |
||||
quickCheck (functorCompose' :: ThreeComp) |
||||
quickCheck (functorCompose' :: Three'Comp) |
||||
quickCheck (functorCompose' :: FourComp) |
||||
quickCheck (functorCompose' :: Four'Comp) |
Loading…
Reference in new issue