{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RebindableSyntax #-}
{-# OPTIONS_GHC -fplugin Control.Super.Monad.Plugin #-}
module Control.Super.Monad.Constrained.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
, (<$!>)
, (<$>)
, 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, const
, not
, fromInteger
, otherwise
, (<=), (-) )
import Control.Super.Monad.Constrained
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 b) => (a -> n b) -> m a -> p b
f =<< ma = ma >>= f
(>=>) :: (Bind m n p, BindCts m n p b c) => (a -> m b) -> (b -> n c) -> a -> p c
(>=>) f g x = f x >>= g
(<=<) :: (Bind m n p, BindCts m n p b c) => (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 [b]
, Bind m n n, BindCts m n n b [b]
, FunctorCts n [b] [b]
) => (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 [b]
, Bind m n n, BindCts m n n b [b]
, FunctorCts n [b] (), FunctorCts n [b] [b]
) => (a -> m b) -> [a] -> n ()
mapM_ f = void . mapM f
forM :: ( Return n, ReturnCts n [b]
, Bind m n n, BindCts m n n b [b]
, FunctorCts n [b] [b]
) => [a] -> (a -> m b) -> n [b]
forM = flip mapM
forM_ :: ( Return n, ReturnCts n [b]
, Bind m n n, BindCts m n n b [b]
, FunctorCts n [b] (), FunctorCts n [b] [b]
) => [a] -> (a -> m b) -> n ()
forM_ xs = void . forM xs
join :: (Bind m n p, BindCts m n p (n a) a) => m (n a) -> p a
join k = k >>= id
void :: (Functor m, FunctorCts m a ()) => m a -> m ()
void = fmap (const ())
voidA :: ( Applicative m n n, ApplicativeCtsR m n n a ()
, Return n, ReturnCts n ()
) => m a -> n ()
voidA = (*> pure ())
voidM :: ( Bind m n n, BindCts m n n a ()
, Return n, ReturnCts n ()
) => m a -> n ()
voidM = (>> return ())
sequence :: ( Return n, ReturnCts n [b]
, Bind m n n, BindCts m n n b [b]
, FunctorCts n [b] [b]
) => [m b] -> n [b]
sequence = mapM id
sequence_ :: ( Return n, ReturnCts n [b]
, Bind m n n, BindCts m n n b [b]
, FunctorCts n [b] (), FunctorCts n [b] [b]
) => [m b] -> n ()
sequence_ = void . sequence
forever :: (Bind m n n, BindCts m n n a b) => m a -> n b
forever na = na >> forever na
filterM :: ( Bind m n n, BindCts m n n Bool [a]
, Return n, ReturnCts n [a]
, FunctorCts n [a] [a])
=> (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 [(b, c)]
, Bind m n n, BindCts m n n (b, c) [(b, c)]
, FunctorCts n [(b, c)] ([b], [c]), FunctorCts n [(b, c)] [(b, c)]
) => (a -> m (b, c)) -> [a] -> n ([b], [c])
mapAndUnzipM f xs = liftM P.unzip (forM xs f)
zipWithM :: ( Return n, ReturnCts n [c]
, Bind m n n, BindCts m n n c [c]
, FunctorCts n [c] [c]
) => (a -> b -> m c) -> [a] -> [b] -> n [c]
zipWithM f xs ys = sequence $ P.zipWith f xs ys
zipWithM_ :: ( Return n, ReturnCts n [c]
, Bind m n n, BindCts m n n c [c]
, FunctorCts n [c] (), FunctorCts n [c] [c]
) => (a -> b -> m c) -> [a] -> [b] -> n ()
zipWithM_ f xs ys = void $ zipWithM f xs ys
foldM :: ( P.Foldable t
, Return m, ReturnCts m b
, Bind m n m, BindCts m n m b b
) => (b -> a -> n b) -> b -> t a -> m b
foldM f e = P.foldl f' (return e)
where f' nb a = nb >>= \b -> f b a
foldM_ :: ( P.Foldable t
, Return m, ReturnCts m b
, Bind m n m, BindCts m n m b b
, FunctorCts m b ()
) => (b -> a -> n b) -> b -> t a -> m ()
foldM_ f e = void . foldM f e
replicateM :: ( Return n, ReturnCts n [a]
, Bind m n n, BindCts m n n a [a]
, FunctorCts n [a] [a]
) => 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 [a]
, Bind m n n, BindCts m n n a [a]
, FunctorCts n [a] (), FunctorCts n [a] [a]
) => Int -> m a -> n ()
replicateM_ n = void . replicateM n
liftM :: (Functor m, FunctorCts m a b) => (a -> b) -> m a -> m b
liftM f ma = fmap f ma
{-# ANN liftM' "HLint: ignore" #-}
liftM' :: ( Return n, ReturnCts n b
, Bind m n n, BindCts m n n a b
) => (a -> b) -> m a -> n b
liftM' f ma = ma >>= (return . f)
liftM2 :: (Bind m n p, BindCts m n p a c
, FunctorCts n b c
) => (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 a d
, Bind n p q, BindCts n p q b d
, FunctorCts p c d)
=> (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 (a -> b) b
, FunctorCts n a b
) => m (a -> b) -> n a -> p b
ap mf na = do
f <- mf
fmap f na
infixl 4 <$>
(<$>) :: ( Return n, ReturnCts n b
, Bind m n n, BindCts m n n a b
) => (a -> b) -> m a -> n b
f <$> m = do
x <- m
return $ f x
infixl 4 <$!>
(<$!>) :: ( Return n, ReturnCts n b
, Bind m n n, BindCts m n n a b
) => (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 b c
, FunctorCts m a (b -> c)
) => (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 (a -> b) b
, FunctorCts m a ((a -> b) -> b)
) => m a -> n (a -> b) -> p b
(<**>) = liftA2 (\a f -> f a)
liftA :: (Return m, ReturnCts m (a -> b), Applicative m m n, ApplicativeCts m m n a b) => (a -> b) -> m a -> n b
liftA f ma = pure f <*> ma
liftA3 :: ( Applicative m n p, ApplicativeCts m n p b (c -> d)
, Applicative p p q, ApplicativeCts p p q c d
, FunctorCts m a (b -> c -> d)
) => (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 [a] [a]
, Return n, ReturnCts n [a]
, FunctorCts m Bool ([a] -> [a])
) => (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 [b]
, Applicative m n n, ApplicativeCts m n n [b] [b]
, FunctorCts m b ([b] -> [b])
) => (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 [b]
, Applicative m n n, ApplicativeCts m n n [b] [b]
, FunctorCts m b ([b] -> [b])
, FunctorCts n [b] ()
) => (a -> m b) -> [a] -> n ()
mapA_ f = void . mapA f
forA :: ( Return n, ReturnCts n [b]
, Applicative m n n, ApplicativeCts m n n [b] [b]
, FunctorCts m b ([b] -> [b])
) => [a] -> (a -> m b) -> n [b]
forA = flip mapA
forA_ :: ( Return n, ReturnCts n [b]
, Applicative m n n, ApplicativeCts m n n [b] [b]
, FunctorCts m b ([b] -> [b])
, FunctorCts n [b] ()
) => [a] -> (a -> m b) -> n ()
forA_ xs = void . forA xs
sequenceA :: ( Return n, ReturnCts n [a]
, Applicative m n n, ApplicativeCts m n n [a] [a]
, FunctorCts m a ([a] -> [a])
) => [m a] -> n [a]
sequenceA = P.foldr (\ ma nas -> fmap (\ a as -> a : as) ma <*> nas) (pure [])
sequenceA_ :: ( Return n, ReturnCts n [a]
, Applicative m n n, ApplicativeCts m n n [a] [a]
, FunctorCts m a ([a] -> [a])
, FunctorCts n [a] ()
) => [m a] -> n ()
sequenceA_ = void . sequenceA
traverse :: ( Return n, ReturnCts n [b]
, Applicative m n n, ApplicativeCts m n n [b] [b]
, FunctorCts m b ([b] -> [b])
) => (a -> m b) -> [a] -> n [b]
traverse f mas = sequenceA $ fmap f mas
mapAndUnzipA :: ( Return n, ReturnCts n [(b, c)]
, Applicative m n n, ApplicativeCts m n n [(b, c)] [(b, c)]
, FunctorCts m (b, c) ([(b, c)] -> [(b, c)])
, FunctorCts n [(b, c)] ([b], [c])
) => (a -> m (b,c)) -> [a] -> n ([b], [c])
mapAndUnzipA f xs = fmap P.unzip $ traverse f xs
zipWithA :: ( Return n, ReturnCts n [c]
, Applicative m n n, ApplicativeCts m n n [c] [c]
, FunctorCts m c ([c] -> [c])
) => (a -> b -> m c) -> [a] -> [b] -> n [c]
zipWithA f xs ys = sequenceA (P.zipWith f xs ys)
zipWithA_ :: ( Return n, ReturnCts n [c]
, Applicative m n n, ApplicativeCts m n n [c] [c]
, FunctorCts m c ([c] -> [c])
, FunctorCts n [c] ()
) => (a -> b -> m c) -> [a] -> [b] -> n ()
zipWithA_ f xs ys = sequenceA_ (P.zipWith f xs ys)
replicateA :: ( Return n, ReturnCts n [a]
, Applicative m n n, ApplicativeCts m n n [a] [a]
, FunctorCts m a ([a] -> [a])
) => 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 [a]
, Applicative m n n, ApplicativeCts m n n [a] [a]
, FunctorCts m a ([a] -> [a])
, FunctorCts n [a] ()
) => Int -> m a -> n ()
replicateA_ cnt0 = void . replicateA cnt0
whenA :: ( Return n, ReturnCts n ()
, Applicative m n n, ApplicativeCtsR m n n () ()
) => Bool -> m () -> n ()
whenA True s = voidA s
whenA False _ = return ()
unlessA :: ( Return n, ReturnCts n ()
, Applicative m n n, ApplicativeCtsR m n n () ()
) => Bool -> m () -> n ()
unlessA b = whenA (not b)