module Control.Alternative.Pointed
( PointedAlternative
, someLazy
, manyLazy
, ascertain
, ascertainA
, (<|!>)
, (<!|>)
, desperately
) where
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Identity
import qualified Data.List.NonEmpty as NE
import Control.Monad.Trans.State
import Control.Applicative
import Control.Monad.Identity
import Control.Monad
import Data.Maybe
import Control.Monad.Trans.Identity
import Data.List
import Data.Foldable
class Alternative f => PointedAlternative f g | f -> g, g -> f where
coerceToNonempty :: f a -> g a
embed :: g a -> f a
someLazy :: f a -> f (NE.NonEmpty a)
someLazy v = coerceToNonempty <$> some_v
where
many_v = ascertain [] some_v
some_v = (:) <$> v <*> embed many_v
manyLazy :: f a -> g [a]
manyLazy v = many_v
where
many_v = ascertain [] some_v
some_v = (:) <$> v <*> embed many_v
ascertain :: PointedAlternative f g => a -> f a -> g a
ascertain x = coerceToNonempty . (<|> pure x)
ascertainA :: PointedAlternative f g => g a -> f a -> g a
ascertainA x = coerceToNonempty . (<|> embed x)
(<!|>) :: PointedAlternative f g => g a -> f a -> g a
x <!|> y = coerceToNonempty $ embed x <|> y
(<|!>) :: PointedAlternative f g => f a -> g a -> g a
x <|!> y = coerceToNonempty $ x <|> embed y
desperately :: PointedAlternative f g => f a -> g a
desperately = coerceToNonempty . asum . repeat
instance PointedAlternative Maybe Identity where
coerceToNonempty = Identity . fromJust
embed = Just . runIdentity
instance PointedAlternative [] NE.NonEmpty where
coerceToNonempty (x:xs) = x NE.:| xs
embed = NE.toList
instance (Functor m, Monad m) => PointedAlternative (MaybeT m) (IdentityT m) where
coerceToNonempty = IdentityT . liftM fromJust . runMaybeT
embed = MaybeT . liftM Just . runIdentityT
instance (PointedAlternative f g, MonadPlus f) => PointedAlternative (StateT s f) (StateT s g) where
coerceToNonempty = StateT . (.) coerceToNonempty . runStateT
embed = StateT . (.) embed . runStateT