Reputation: 719
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:
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?
Upvotes: 1
Views: 593
Reputation: 76240
pure
?pure
is simply a function to "insert" an object inside a specific Applicative
monad. For example in:
test :: [Int]
test = pure 1 -- [1]
we are inserting 1
into the list monad, which results in the singleton [1]
. If you have already read about the Monad
class, then pure
is basically the same as return
(if you haven't don't worry).
Your instance of Applicative
seems to be working fine.
When running commands in GHCi, you are basically in the IO
monad, which is also an Applicative
. So in general, pure x
returns an IO (type of x)
.
In:
pure (*2) <*> pure 2
you are "putting" (*2)
in an IO
object, then putting 2
in an IO
object as well, and finally calling <*>
as defined in the instance Applicative IO
.
You are not testing your MZipList
instance.
In the second example you are simply calling:
pure ((*2) 2)
If you recall, (*2) 2
simply applies (*2)
to 2
, thus really executing 2 * 2
. So your call is actually:
pure 4
which, in GHCi (still in the context of the IO
monad) returns an IO Int
object.
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:
pure (*2) <*> pure 2
you would write:
pure (*2) <*> (pure 2 :: MZipList Int)
Upvotes: 8