{-# LANGUAGE UndecidableInstances #-}
module Control.Effect.Choose
(
Choose(..)
, (<|>)
, optional
, many
, some
, some1
, Choosing(..)
, Algebra
, Has
, run
) where
import Control.Algebra
import Control.Effect.Choose.Internal (Choose(..))
import Control.Effect.Empty
import Data.Bool (bool)
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.Semigroup as S
(<|>) :: Has Choose sig m => m a -> m a -> m a
a <|> b = send Choose >>= bool b a
{-# INLINE (<|>) #-}
infixl 3 <|>
optional :: Has Choose sig m => m a -> m (Maybe a)
optional a = Just <$> a <|> pure Nothing
{-# INLINE optional #-}
many :: Has Choose sig m => m a -> m [a]
many a = go where go = (:) <$> a <*> go <|> pure []
{-# INLINE many #-}
some :: Has Choose sig m => m a -> m [a]
some a = (:) <$> a <*> many a
{-# INLINE some #-}
some1 :: Has Choose sig m => m a -> m (NonEmpty a)
some1 a = (:|) <$> a <*> many a
{-# INLINE some1 #-}
newtype Choosing m a = Choosing { getChoosing :: m a }
instance Has Choose sig m => S.Semigroup (Choosing m a) where
Choosing m1 <> Choosing m2 = Choosing (m1 <|> m2)
{-# INLINE (<>) #-}
instance (Has Choose sig m, Has Empty sig m) => Monoid (Choosing m a) where
mempty = Choosing empty
{-# INLINE mempty #-}
mappend = (S.<>)
{-# INLINE mappend #-}