Zip.hs 2.48 KB
Newer Older
1
{-# LANGUAGE Safe #-}
2
{-# LANGUAGE TypeOperators #-}
dterei's avatar
dterei committed
3

4 5 6 7
-----------------------------------------------------------------------------
-- |
-- Module      :  Control.Monad.Zip
-- Copyright   :  (c) Nils Schweinsberg 2011,
8
--                (c) George Giorgidze 2011
9 10 11 12 13 14 15 16 17 18
--                (c) University Tuebingen 2011
-- License     :  BSD-style (see the file libraries/base/LICENSE)
-- Maintainer  :  libraries@haskell.org
-- Stability   :  experimental
-- Portability :  portable
--
-- Monadic zipping (used for monad comprehensions)
--
-----------------------------------------------------------------------------

19
module Control.Monad.Zip where
20

Oleg Grenrus's avatar
Oleg Grenrus committed
21 22
import Control.Monad (liftM, liftM2)
import Data.Monoid
23
import GHC.Generics
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

-- | `MonadZip` type class. Minimal definition: `mzip` or `mzipWith`
--
-- Instances should satisfy the laws:
--
-- * Naturality :
--
--   > liftM (f *** g) (mzip ma mb) = mzip (liftM f ma) (liftM g mb)
--
-- * Information Preservation:
--
--   > liftM (const ()) ma = liftM (const ()) mb
--   > ==>
--   > munzip (mzip ma mb) = (ma, mb)
--
class Monad m => MonadZip m where
40
    {-# MINIMAL mzip | mzipWith #-}
41 42 43 44 45 46 47

    mzip :: m a -> m b -> m (a,b)
    mzip = mzipWith (,)

    mzipWith :: (a -> b -> c) -> m a -> m b -> m c
    mzipWith f ma mb = liftM (uncurry f) (mzip ma mb)

48 49 50 51 52
    munzip :: m (a,b) -> (m a, m b)
    munzip mab = (liftM fst mab, liftM snd mab)
    -- munzip is a member of the class because sometimes
    -- you can implement it more efficiently than the
    -- above default code.  See Trac #4370 comment by giorgidze
53

54 55 56
instance MonadZip [] where
    mzip     = zip
    mzipWith = zipWith
57
    munzip   = unzip
dterei's avatar
dterei committed
58

Oleg Grenrus's avatar
Oleg Grenrus committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
instance MonadZip Dual where
    -- Cannot use coerce, it's unsafe
    mzipWith = liftM2

instance MonadZip Sum where
    mzipWith = liftM2

instance MonadZip Product where
    mzipWith = liftM2

instance MonadZip Maybe where
    mzipWith = liftM2

instance MonadZip First where
    mzipWith = liftM2

instance MonadZip Last where
    mzipWith = liftM2

instance MonadZip f => MonadZip (Alt f) where
    mzipWith f (Alt ma) (Alt mb) = Alt (mzipWith f ma mb)
80 81 82 83 84 85 86 87 88 89 90 91 92

-- Instances for GHC.Generics
instance MonadZip Par1 where
    mzipWith = liftM2

instance MonadZip f => MonadZip (Rec1 f) where
    mzipWith f (Rec1 fa) (Rec1 fb) = Rec1 (mzipWith f fa fb)

instance MonadZip f => MonadZip (M1 i c f) where
    mzipWith f (M1 fa) (M1 fb) = M1 (mzipWith f fa fb)

instance (MonadZip f, MonadZip g) => MonadZip (f :*: g) where
    mzipWith f (x1 :*: y1) (x2 :*: y2) = mzipWith f x1 x2 :*: mzipWith f y1 y2