summaryrefslogtreecommitdiff
path: root/TraversableT.hs
diff options
context:
space:
mode:
Diffstat (limited to 'TraversableT.hs')
-rw-r--r--TraversableT.hs94
1 files changed, 94 insertions, 0 deletions
diff --git a/TraversableT.hs b/TraversableT.hs
new file mode 100644
index 00000000..c0e40853
--- /dev/null
+++ b/TraversableT.hs
@@ -0,0 +1,94 @@
1module TraversableT where
2
3import Data.Traversable
4import Control.Monad (join,MonadPlus(..))
5import Control.Monad.Trans.Class (MonadTrans(..))
6import Control.Applicative
7import Data.Foldable (Foldable(foldMap), toList)
8import Data.Maybe (maybeToList)
9
10-- |
11--
12-- /Note:/ this does not yield a monad unless the argument monad is commutative.
13newtype TraversableT t m a = TraversableT { runTraversableT :: m (t a) }
14
15-- | Map between 'TraversableT' computations.
16--
17-- * @'runTraversableT' ('mapTraversableT' f m) = f ('runTraversableT' m)@
18mapTraversableT :: (m (t a) -> n (t b)) -> TraversableT t m a -> TraversableT t n b
19mapTraversableT f m = TraversableT $ f (runTraversableT m)
20
21
22instance (Functor m, Functor t) => Functor (TraversableT t m) where
23 fmap f = mapTraversableT $ fmap $ fmap f
24
25instance (Foldable f, Foldable t) => Foldable (TraversableT t f) where
26 foldMap f (TraversableT a) = foldMap (foldMap f) a
27
28instance (Traversable f, Traversable t) => Traversable (TraversableT t f) where
29 traverse f (TraversableT a) = TraversableT <$> traverse (traverse f) a
30
31instance (Applicative m,Applicative t) => Applicative (TraversableT t m) where
32 pure a = TraversableT $ pure (pure a)
33 f <*> v = TraversableT $ (<*>) <$> runTraversableT f <*> runTraversableT v
34
35instance (Applicative m, Alternative t) => Alternative (TraversableT t m) where
36 empty = TraversableT $ pure empty
37 m <|> n = TraversableT $ (<|>) <$> runTraversableT m <*> runTraversableT n
38
39instance (Monad m, Traversable t, Monad t) => Monad (TraversableT t m) where
40 return = TraversableT . return . return
41 m >>= k = TraversableT $ do
42 a <- runTraversableT m
43 b <- forM a $ runTraversableT . k
44 return (join b)
45 fail s = TraversableT $ return (fail s)
46
47instance (Monad m, Traversable t, MonadPlus t) => MonadPlus (TraversableT t m) where
48 mzero = TraversableT $ return mzero
49 m `mplus` n = TraversableT $ do
50 a <- runTraversableT m
51 b <- runTraversableT n
52 return (a `mplus` b)
53
54instance Applicative t => MonadTrans (TraversableT t) where
55 lift m = TraversableT $ do
56 a <- m
57 return (pure a)
58
59liftT :: Monad m => t a -> TraversableT t m a
60liftT = TraversableT . return
61
62liftMT :: m (t a) -> TraversableT t m a
63liftMT = TraversableT
64
65-- | Lift a @callCC@ operation to the new monad.
66liftCallCC :: Applicative t =>
67 ((( (t a) -> m (t b)) -> m (t a)) -> m (t a)) ->
68 ((a -> TraversableT t m b) -> TraversableT t m a) -> TraversableT t m a
69liftCallCC callCC f = TraversableT $
70 callCC $ \c ->
71 runTraversableT (f (\a -> TraversableT $ c (pure a)))
72
73-- | Lift a @catchError@ operation to the new monad.
74liftCatch :: (m (t a) -> (e -> m (t a)) -> m (t a)) ->
75 TraversableT t m a -> (e -> TraversableT t m a) -> TraversableT t m a
76liftCatch catchError m h = TraversableT $ runTraversableT m
77 `catchError` \e -> runTraversableT (h e)
78
79liftMaybe :: Monad m => Maybe a -> TraversableT [] m a
80liftMaybe = liftT . maybeToList
81
82liftIOMaybe :: IO (Maybe a) -> TraversableT [] IO a
83liftIOMaybe = liftMT . fmap maybeToList
84
85handleT :: ( Monad m
86 , Traversable t ) =>
87 (t a -> TraversableT t m a)
88 -> TraversableT t m a
89 -> TraversableT t m a
90handleT catcher body = TraversableT $ do
91 tx <- runTraversableT body
92 if null (toList tx)
93 then runTraversableT $ catcher tx
94 else return tx