Hacker News new | ask | show | jobs
by pinjo 2790 days ago
An example of this is the two possible applicative instance of list. One is based on the monad instance and does a cross product if presented with two lists. The other zips its arguments. It is the more interesting one imho:

    import Control.Applicative 
    newtype ZList a = ZList { runZList :: [a] } 
    instance Functor ZList where 
        fmap f = ZList . fmap f . runZList

    instance Applicative ZList where 
        pure a = ZList [a]
        (<*>) f x = ZList $ zipper (runZList f) (runZList x)
                where zipper (f:fs) (x:xs) = f x : zipper fs xs 
                      zipper [] _ = [] 
                      zipper _ [] = []
Difference of behaviour:

   *Main> ZipList [(*3),(*5),(*6)] <*> ZipList [1,2,3,4] 
    ZipList {getZipList = [3,10,18]}
   *Main> [(*3),(*5),(*6)] <*> [1,2,3,4]
    [3,6,9,12,5,10,15,20,6,12,18,24]
    *Main>
1 comments

Yes, though that definition results in:

    pure id <*> ZipList [x, y, z] == ZipList [x]
and thus breaks one of the Applicative laws:

    pure id <*> v == v
The standard ZipList definition is `pure a = ZipList (repeat a)` (an infinite list).

The issue with defining a Monad instance for ZList is that mapping the function on the right of (>>=) over the ZList on the left gets you a ZList of `ZList b`, with no meaningful way to zip these ZLists together.