1{-# LANGUAGE Safe #-} 2{-# LANGUAGE TypeOperators #-} 3 4----------------------------------------------------------------------------- 5-- | 6-- Module : Control.Monad.Zip 7-- Copyright : (c) Nils Schweinsberg 2011, 8-- (c) George Giorgidze 2011 9-- (c) University Tuebingen 2011 10-- License : BSD-style (see the file libraries/base/LICENSE) 11-- Maintainer : libraries@haskell.org 12-- Stability : experimental 13-- Portability : portable 14-- 15-- Monadic zipping (used for monad comprehensions) 16-- 17----------------------------------------------------------------------------- 18 19module Control.Monad.Zip where 20 21import Control.Monad (liftM, liftM2) 22import Data.Functor.Identity 23import Data.Monoid 24import Data.Ord ( Down(..) ) 25import Data.Proxy 26import qualified Data.List.NonEmpty as NE 27import GHC.Generics 28 29-- | Instances should satisfy the laws: 30-- 31-- [Naturality] 32-- 33-- @'liftM' (f 'Control.Arrow.***' g) ('mzip' ma mb) 34-- = 'mzip' ('liftM' f ma) ('liftM' g mb)@ 35-- 36-- [Information Preservation] 37-- 38-- @'liftM' ('Prelude.const' ()) ma = 'liftM' ('Prelude.const' ()) mb@ 39-- implies 40-- @'munzip' ('mzip' ma mb) = (ma, mb)@ 41-- 42class Monad m => MonadZip m where 43 {-# MINIMAL mzip | mzipWith #-} 44 45 mzip :: m a -> m b -> m (a,b) 46 mzip = mzipWith (,) 47 48 mzipWith :: (a -> b -> c) -> m a -> m b -> m c 49 mzipWith f ma mb = liftM (uncurry f) (mzip ma mb) 50 51 munzip :: m (a,b) -> (m a, m b) 52 munzip mab = (liftM fst mab, liftM snd mab) 53 -- munzip is a member of the class because sometimes 54 -- you can implement it more efficiently than the 55 -- above default code. See #4370 comment by giorgidze 56 57-- | @since 4.3.1.0 58instance MonadZip [] where 59 mzip = zip 60 mzipWith = zipWith 61 munzip = unzip 62 63-- | @since 4.9.0.0 64instance MonadZip NE.NonEmpty where 65 mzip = NE.zip 66 mzipWith = NE.zipWith 67 munzip = NE.unzip 68 69-- | @since 4.8.0.0 70instance MonadZip Identity where 71 mzipWith = liftM2 72 munzip (Identity (a, b)) = (Identity a, Identity b) 73 74-- | @since 4.8.0.0 75instance MonadZip Dual where 76 -- Cannot use coerce, it's unsafe 77 mzipWith = liftM2 78 79-- | @since 4.8.0.0 80instance MonadZip Sum where 81 mzipWith = liftM2 82 83-- | @since 4.8.0.0 84instance MonadZip Product where 85 mzipWith = liftM2 86 87-- | @since 4.8.0.0 88instance MonadZip Maybe where 89 mzipWith = liftM2 90 91-- | @since 4.8.0.0 92instance MonadZip First where 93 mzipWith = liftM2 94 95-- | @since 4.8.0.0 96instance MonadZip Last where 97 mzipWith = liftM2 98 99-- | @since 4.8.0.0 100instance MonadZip f => MonadZip (Alt f) where 101 mzipWith f (Alt ma) (Alt mb) = Alt (mzipWith f ma mb) 102 103-- | @since 4.9.0.0 104instance MonadZip Proxy where 105 mzipWith _ _ _ = Proxy 106 107-- Instances for GHC.Generics 108-- | @since 4.9.0.0 109instance MonadZip U1 where 110 mzipWith _ _ _ = U1 111 112-- | @since 4.9.0.0 113instance MonadZip Par1 where 114 mzipWith = liftM2 115 116-- | @since 4.9.0.0 117instance MonadZip f => MonadZip (Rec1 f) where 118 mzipWith f (Rec1 fa) (Rec1 fb) = Rec1 (mzipWith f fa fb) 119 120-- | @since 4.9.0.0 121instance MonadZip f => MonadZip (M1 i c f) where 122 mzipWith f (M1 fa) (M1 fb) = M1 (mzipWith f fa fb) 123 124-- | @since 4.9.0.0 125instance (MonadZip f, MonadZip g) => MonadZip (f :*: g) where 126 mzipWith f (x1 :*: y1) (x2 :*: y2) = mzipWith f x1 x2 :*: mzipWith f y1 y2 127 128-- instances for Data.Ord 129 130-- | @since 4.12.0.0 131instance MonadZip Down where 132 mzipWith = liftM2 133