I'm doing the exercises from Typeclassopedia; in the Applicative section, I write ZipList's pure function, and check whether it follows the Applicative Laws.
I've checked:
- identity law
- interchange law
- composition law
But when I try to check the "homomorphism" law, I find that GHCi doesn't get the result as an MZipList.
I think this is because I miss to designate the pure to my Applicative type class. How can I run a pure function without <*> it to Applicative immediately?
Here's the MZipList definition and class instances:
newtype MZipList a = MZipList { getZipList :: [a] }
deriving (Show)
instance Functor MZipList where
fmap gs x = pure gs <*> x
instance Applicative MZipList where
pure a= MZipList (repeat a)
(MZipList gs) <*> (MZipList xs) = MZipList (zipWith ($) gs xs)
When I check the "Interchange" law, for example:
*Main> (MZipList [(*2),(*3),(*4)]) <*> pure (2)
MZipList {getZipList = [4,6,8]}
*Main> pure ($ 2) <*> (MZipList [(*2),(*3),(*4)])
MZipList {getZipList = [4,6,8]}
But when I check the "Homomorphism" law , the MZipList's pure is not called:
*Main> pure (*2) <*> pure 2
4
*Main> pure ((*2) 2)
4
*Main>
Why is that?
What is
pure?pureis simply a function to "insert" an object inside a specificApplicativemonad. For example in:we are inserting
1into the list monad, which results in the singleton[1]. If you have already read about theMonadclass, thenpureis basically the same asreturn(if you haven't don't worry).Your instance of
Applicativeseems to be working fine.Your tests
When running commands in GHCi, you are basically in the
IOmonad, which is also anApplicative. So in general,pure xreturns anIO (type of x).In:
you are "putting"
(*2)in anIOobject, then putting2in anIOobject as well, and finally calling<*>as defined in theinstance Applicative IO.You are not testing your
MZipListinstance.In the second example you are simply calling:
If you recall,
(*2) 2simply applies(*2)to2, thus really executing2 * 2. So your call is actually:which, in GHCi (still in the context of the
IOmonad) returns anIO Intobject.How to test properly
To test the "homomorphism" law, you just need to give the compiler a small hint as to what type you really want:
So instead of:
you would write:
Live demo