{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RebindableSyntax #-}
{-# OPTIONS_GHC -fplugin Control.Super.Monad.Plugin #-}
module Control.Super.Monad.Functions
(
mapM, mapM_
, forM, forM_
, sequence, sequence_
, (=<<)
, (>=>), (<=<)
, forever, void, voidM
, join
, filterM
, mapAndUnzipM
, zipWithM, zipWithM_
, foldM, foldM_
, replicateM, replicateM_
, when, unless
, liftM, liftM', liftM2, liftM3
, ap
, (<$!>)
, (P.<$>), (P.<$)
, ifThenElse
, liftA3, liftA2, liftA
, voidA
, (<**>)
, mapA, mapA_
, forA, forA_
, filterA
, sequenceA, sequenceA_
, traverse
, zipWithA, zipWithA_
, mapAndUnzipA
, replicateA, replicateA_
, whenA, unlessA
) where
import qualified Prelude as P
import Prelude
( Bool(..), Int
, (.), ($)
, id, flip
, not
, fromInteger
, otherwise
, (<=), (-) )
import Control.Monad ( void )
import Control.Super.Monad
ifThenElse :: Bool -> a -> a -> a
ifThenElse True t _f = t
ifThenElse False _t f = f
infixr 1 =<<
infixr 1 >=>
infixr 1 <=<
(=<<) :: (Bind m n p, BindCts m n p) => (a -> n b) -> m a -> p b
f =<< ma = ma >>= f
(>=>) :: (Bind m n p, BindCts m n p) => (a -> m b) -> (b -> n c) -> a -> p c
(>=>) f g x = f x >>= g
(<=<) :: (Bind m n p, BindCts m n p) => (b -> n c) -> (a -> m b) -> a -> p c
(<=<) g f x = f x >>= g
when :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => Bool -> m () -> n ()
when True s = voidM s
when False _ = return ()
unless :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => Bool -> m () -> n ()
unless b = when (not b)
mapM :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => (a -> m b) -> [a] -> n [b]
mapM f = P.foldr k (return [])
where
k a r = do
x <- f a
fmap (x :) r
mapM_ :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => (a -> m b) -> [a] -> n ()
mapM_ f = void . mapM f
forM :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => [a] -> (a -> m b) -> n [b]
forM = flip mapM
forM_ :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => [a] -> (a -> m b) -> n ()
forM_ xs = void . forM xs
join :: (Bind m n p, BindCts m n p) => m (n a) -> p a
join k = k >>= id
voidA :: ( Applicative m n n, ApplicativeCts m n n
, Return n, ReturnCts n
) => m a -> n ()
voidA = (*> pure ())
voidM :: ( Bind m n n, BindCts m n n
, Return n, ReturnCts n
) => m a -> n ()
voidM = (>> return ())
sequence :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => [m b] -> n [b]
sequence = mapM id
sequence_ :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => [m b] -> n ()
sequence_ = void . sequence
forever :: (Applicative m n n, ApplicativeCts m n n) => m a -> n b
forever na = na *> forever na
filterM :: ( Bind m n n, BindCts m n n
, Return n, ReturnCts n
) => (a -> m Bool) -> [a] -> n [a]
filterM _f [] = return []
filterM f (x : xs) = do
keep <- f x
if keep
then fmap (x :) $ filterM f xs
else filterM f xs
mapAndUnzipM :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => (a -> m (b, c)) -> [a] -> n ([b], [c])
mapAndUnzipM f xs = liftM P.unzip (forM xs f)
zipWithM :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => (a -> b -> m c) -> [a] -> [b] -> n [c]
zipWithM f xs ys = sequence $ P.zipWith f xs ys
zipWithM_ :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => (a -> b -> m c) -> [a] -> [b] -> n ()
zipWithM_ f xs ys = void $ zipWithM f xs ys
foldM :: ( P.Foldable t
, Return m, ReturnCts m
, Bind m n m, BindCts m n m
) => (b -> a -> n b) -> b -> t a -> m b
foldM f e = P.foldl f' (return e)
where f' mb a = mb >>= \b -> f b a
foldM_ :: ( P.Foldable t
, Return m, ReturnCts m
, Bind m n m, BindCts m n m
) => (b -> a -> n b) -> b -> t a -> m ()
foldM_ f e = void . foldM f e
replicateM :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => Int -> m a -> n [a]
replicateM n _ma | n <= 0 = return []
replicateM n ma = do
a <- ma
fmap (a :) $ replicateM (n - 1) ma
replicateM_ :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => Int -> m a -> n ()
replicateM_ n = void . replicateM n
liftM :: (Functor m) => (a -> b) -> m a -> m b
liftM f ma = fmap f ma
{-# ANN liftM' "HLint: ignore" #-}
liftM' :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => (a -> b) -> m a -> n b
liftM' f ma = ma >>= (return . f)
liftM2 :: ( Bind m n p, BindCts m n p
) => (a -> b -> c) -> m a -> n b -> p c
liftM2 f ma nb = do
a <- ma
fmap (f a) nb
liftM3 :: ( Bind m q q, BindCts m q q
, Bind n p q, BindCts n p q)
=> (a -> b -> c -> d) -> m a -> n b -> p c -> q d
liftM3 f ma nb pc = do
a <- ma
b <- nb
fmap (f a b) pc
ap :: ( Bind m n p, BindCts m n p
) => m (a -> b) -> n a -> p b
ap mf na = do
f <- mf
fmap f na
infixl 4 <$!>
(<$!>) :: ( Return n, ReturnCts n
, Bind m n n, BindCts m n n
) => (a -> b) -> m a -> n b
f <$!> m = do
x <- m
let z = f x
z `P.seq` return z
liftA2 :: (Applicative m n p, ApplicativeCts m n p) => (a -> b -> c) -> m a -> n b -> p c
liftA2 f fa fb = fmap f fa <*> fb
(<**>) :: (Applicative m n p, ApplicativeCts m n p) => m a -> n (a -> b) -> p b
(<**>) = liftA2 (\a f -> f a)
liftA :: (Return m, ReturnCts m, Applicative m m n, ApplicativeCts m m n) => (a -> b) -> m a -> n b
liftA f ma = pure f <*> ma
liftA3 :: (Applicative m n p, ApplicativeCts m n p, Applicative p p q, ApplicativeCts p p q) => (a -> b -> c -> d) -> m a -> n b -> p c -> q d
liftA3 f ma nb pc = liftA2 f ma nb <*> pc
filterA :: ( Applicative m n n, ApplicativeCts m n n
, Return n, ReturnCts n
) => (a -> m Bool) -> [a] -> n [a]
filterA p = P.foldr (\ x -> liftA2 (\ flg -> if flg then (x:) else id) (p x)) (pure [])
mapA :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => (a -> m b) -> [a] -> n [b]
mapA f = P.foldr k (return [])
where
k a r = fmap (\x xs -> x : xs) (f a) <*> r
mapA_ :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => (a -> m b) -> [a] -> n ()
mapA_ f = void . mapA f
forA :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => [a] -> (a -> m b) -> n [b]
forA = flip mapA
forA_ :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => [a] -> (a -> m b) -> n ()
forA_ xs = void . forA xs
sequenceA :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => [m a] -> n [a]
sequenceA = P.foldr (\ ma nas -> fmap (\ a as -> a : as) ma <*> nas) (pure [])
sequenceA_ :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => [m a] -> n ()
sequenceA_ = void . sequenceA
traverse :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => (a -> m b) -> [a] -> n [b]
traverse f mas = sequenceA $ fmap f mas
mapAndUnzipA :: (Return n, ReturnCts n, Applicative m n n, ApplicativeCts m n n) => (a -> m (b,c)) -> [a] -> n ([b], [c])
mapAndUnzipA f xs = fmap P.unzip $ traverse f xs
zipWithA :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => (a -> b -> m c) -> [a] -> [b] -> n [c]
zipWithA f xs ys = sequenceA (P.zipWith f xs ys)
zipWithA_ :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => (a -> b -> m c) -> [a] -> [b] -> n ()
zipWithA_ f xs ys = sequenceA_ (P.zipWith f xs ys)
replicateA :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => Int -> m a -> n [a]
replicateA cnt0 f =
loop cnt0
where
loop cnt
| cnt <= 0 = pure []
| otherwise = liftA2 (:) f (loop (cnt - 1))
replicateA_ :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => Int -> m a -> n ()
replicateA_ cnt0 = void . replicateA cnt0
whenA :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => Bool -> m () -> n ()
whenA True s = voidA s
whenA False _ = return ()
unlessA :: ( Return n, ReturnCts n
, Applicative m n n, ApplicativeCts m n n
) => Bool -> m () -> n ()
unlessA b = whenA (not b)