Update Trac ticket URLs to point to GitLab
[ghc.git] / libraries / base / Control / Monad / Zip.hs
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
19 module Control.Monad.Zip where
20
21 import Control.Monad (liftM, liftM2)
22 import Data.Functor.Identity
23 import Data.Monoid
24 import Data.Ord ( Down(..) )
25 import Data.Proxy
26 import qualified Data.List.NonEmpty as NE
27 import 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 --
42 class 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
58 instance MonadZip [] where
59 mzip = zip
60 mzipWith = zipWith
61 munzip = unzip
62
63 -- | @since 4.9.0.0
64 instance MonadZip NE.NonEmpty where
65 mzip = NE.zip
66 mzipWith = NE.zipWith
67 munzip = NE.unzip
68
69 -- | @since 4.8.0.0
70 instance MonadZip Identity where
71 mzipWith = liftM2
72 munzip (Identity (a, b)) = (Identity a, Identity b)
73
74 -- | @since 4.8.0.0
75 instance MonadZip Dual where
76 -- Cannot use coerce, it's unsafe
77 mzipWith = liftM2
78
79 -- | @since 4.8.0.0
80 instance MonadZip Sum where
81 mzipWith = liftM2
82
83 -- | @since 4.8.0.0
84 instance MonadZip Product where
85 mzipWith = liftM2
86
87 -- | @since 4.8.0.0
88 instance MonadZip Maybe where
89 mzipWith = liftM2
90
91 -- | @since 4.8.0.0
92 instance MonadZip First where
93 mzipWith = liftM2
94
95 -- | @since 4.8.0.0
96 instance MonadZip Last where
97 mzipWith = liftM2
98
99 -- | @since 4.8.0.0
100 instance 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
104 instance MonadZip Proxy where
105 mzipWith _ _ _ = Proxy
106
107 -- Instances for GHC.Generics
108 -- | @since 4.9.0.0
109 instance MonadZip U1 where
110 mzipWith _ _ _ = U1
111
112 -- | @since 4.9.0.0
113 instance MonadZip Par1 where
114 mzipWith = liftM2
115
116 -- | @since 4.9.0.0
117 instance 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
121 instance 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
125 instance (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
131 instance MonadZip Down where
132 mzipWith = liftM2