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
?pure
is simply a function to "insert" an object inside a specificApplicative
monad. For example in:we are inserting
1
into the list monad, which results in the singleton[1]
. If you have already read about theMonad
class, thenpure
is basically the same asreturn
(if you haven't don't worry).Your instance of
Applicative
seems to be working fine.Your tests
When running commands in GHCi, you are basically in the
IO
monad, which is also anApplicative
. So in general,pure x
returns anIO (type of x)
.In:
you are "putting"
(*2)
in anIO
object, then putting2
in anIO
object as well, and finally calling<*>
as defined in theinstance Applicative IO
.You are not testing your
MZipList
instance.In the second example you are simply calling:
If you recall,
(*2) 2
simply applies(*2)
to2
, thus really executing2 * 2
. So your call is actually:which, in GHCi (still in the context of the
IO
monad) returns anIO Int
object.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