Ensure the orientation of var-var equalities is correct for instatiation
[ghc-hetmet.git] / compiler / utils / MonadUtils.hs
1
2 -- | Utilities related to Monad and Applicative classes
3 --   Mostly for backwards compatability.
4
5 module MonadUtils
6         ( Applicative(..)
7         , (<$>)
8         
9         , MonadFix(..)
10         , MonadIO(..)
11         
12         , liftIO1, liftIO2, liftIO3, liftIO4
13
14         , zipWith3M        
15         , mapAndUnzipM, mapAndUnzip3M, mapAndUnzip4M
16         , mapAccumLM
17         , mapSndM
18         , concatMapM
19         , mapMaybeM
20         , anyM, allM
21         , foldlM, foldrM
22         ) where
23
24 ----------------------------------------------------------------------------------------
25 -- Detection of available libraries
26 ----------------------------------------------------------------------------------------
27
28 -- we don't depend on MTL for now
29 #define HAVE_MTL 0
30
31 ----------------------------------------------------------------------------------------
32 -- Imports
33 ----------------------------------------------------------------------------------------
34
35 import Maybes
36
37 import Control.Applicative
38 #if HAVE_MTL
39 import Control.Monad.Trans
40 #endif
41 import Control.Monad
42 import Control.Monad.Fix
43
44 ----------------------------------------------------------------------------------------
45 -- MTL
46 ----------------------------------------------------------------------------------------
47
48 #if !HAVE_MTL
49
50 class Monad m => MonadIO m where
51     liftIO :: IO a -> m a
52
53 instance MonadIO IO where liftIO = id
54 #endif
55
56 ----------------------------------------------------------------------------------------
57 -- Lift combinators
58 --  These are used throughout the compiler
59 ----------------------------------------------------------------------------------------
60
61 -- | Lift an 'IO' operation with 1 argument into another monad
62 liftIO1 :: MonadIO m => (a -> IO b) -> a -> m b
63 liftIO1 = (.) liftIO
64
65 -- | Lift an 'IO' operation with 2 arguments into another monad
66 liftIO2 :: MonadIO m => (a -> b -> IO c) -> a -> b -> m c
67 liftIO2 = ((.).(.)) liftIO
68
69 -- | Lift an 'IO' operation with 3 arguments into another monad
70 liftIO3 :: MonadIO m => (a -> b -> c -> IO d) -> a -> b -> c -> m d
71 liftIO3 = ((.).((.).(.))) liftIO
72
73 -- | Lift an 'IO' operation with 4 arguments into another monad
74 liftIO4 :: MonadIO m => (a -> b -> c -> d -> IO e) -> a -> b -> c -> d -> m e
75 liftIO4 = (((.).(.)).((.).(.))) liftIO
76
77 ----------------------------------------------------------------------------------------
78 -- Common functions
79 --  These are used throughout the compiler
80 ----------------------------------------------------------------------------------------
81
82 zipWith3M :: Monad m => (a -> b -> c -> m d) -> [a] -> [b] -> [c] -> m [d]
83 zipWith3M _ []     _      _      = return []
84 zipWith3M _ _      []     _      = return []
85 zipWith3M _ _      _      []     = return []
86 zipWith3M f (x:xs) (y:ys) (z:zs) 
87   = do { r  <- f x y z
88        ; rs <- zipWith3M f xs ys zs
89        ; return $ r:rs
90        }
91
92 -- | mapAndUnzipM for triples
93 mapAndUnzip3M :: Monad m => (a -> m (b,c,d)) -> [a] -> m ([b],[c],[d])
94 mapAndUnzip3M _ []     = return ([],[],[])
95 mapAndUnzip3M f (x:xs) = do
96     (r1,  r2,  r3)  <- f x
97     (rs1, rs2, rs3) <- mapAndUnzip3M f xs
98     return (r1:rs1, r2:rs2, r3:rs3)
99
100 mapAndUnzip4M :: Monad m => (a -> m (b,c,d,e)) -> [a] -> m ([b],[c],[d],[e])
101 mapAndUnzip4M _ []     = return ([],[],[],[])
102 mapAndUnzip4M f (x:xs) = do
103     (r1,  r2,  r3,  r4)  <- f x
104     (rs1, rs2, rs3, rs4) <- mapAndUnzip4M f xs
105     return (r1:rs1, r2:rs2, r3:rs3, r4:rs4)
106
107 -- | Monadic version of mapAccumL
108 mapAccumLM :: Monad m
109             => (acc -> x -> m (acc, y)) -- ^ combining funcction
110             -> acc                      -- ^ initial state
111             -> [x]                      -- ^ inputs
112             -> m (acc, [y])             -- ^ final state, outputs
113 mapAccumLM _ s []     = return (s, [])
114 mapAccumLM f s (x:xs) = do
115     (s1, x')  <- f s x
116     (s2, xs') <- mapAccumLM f s1 xs
117     return    (s2, x' : xs')
118
119 -- | Monadic version of mapSnd
120 mapSndM :: Monad m => (b -> m c) -> [(a,b)] -> m [(a,c)]
121 mapSndM _ []         = return []
122 mapSndM f ((a,b):xs) = do { c <- f b; rs <- mapSndM f xs; return ((a,c):rs) }
123
124 -- | Monadic version of concatMap
125 concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
126 concatMapM f xs = liftM concat (mapM f xs)
127
128 -- | Monadic version of mapMaybe
129 mapMaybeM :: (Monad m) => (a -> m (Maybe b)) -> [a] -> m [b]
130 mapMaybeM f = liftM catMaybes . mapM f
131
132 -- | Monadic version of 'any', aborts the computation at the first @True@ value
133 anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool
134 anyM _ []     = return False
135 anyM f (x:xs) = do b <- f x
136                    if b then return True 
137                         else anyM f xs
138
139 -- | Monad version of 'all', aborts the computation at the first @False@ value
140 allM :: Monad m => (a -> m Bool) -> [a] -> m Bool
141 allM _ []     = return True
142 allM f (b:bs) = (f b) >>= (\bv -> if bv then allM f bs else return False)
143
144 -- | Monadic version of foldl
145 foldlM :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
146 foldlM = foldM
147
148 -- | Monadic version of foldr
149 foldrM        :: (Monad m) => (b -> a -> m a) -> a -> [b] -> m a
150 foldrM _ z []     = return z
151 foldrM k z (x:xs) = do { r <- foldrM k z xs; k x r }