module Text.XML.Enumerator.Combinators.General ( chooseSplit , permute , permuteFallback ) where import Control.Monad (liftM) -- | Like 'choose', but also returns the list of elements that were /not/ chosen. chooseSplit :: (Monad m) => (a -> m (Maybe b)) -> [a] -> m (Maybe (b, [a])) chooseSplit f xs = go xs [] where go [] _ = return Nothing go (i:is) is' = do x <- f i case x of Nothing -> go is (i : is') Just a -> return $ Just (a, is' ++ is) -- | Permute all parsers until none return 'Just'. permute :: (Monad m) => (a -> m (Maybe b)) -> [a] -> m (Maybe [b]) permute _ [] = return (Just []) permute f is = do x <- chooseSplit f is case x of Nothing -> return Nothing Just (a, is') -> fmap (a:) `liftM` permute f is' -- | Permute all parsers until none return 'Just', but always test some fallback parsers. permuteFallback :: (Monad m) => m (Maybe [b]) -> (a -> m (Maybe b)) -> [a] -> m (Maybe [b]) permuteFallback _ _ [] = return (Just []) permuteFallback fb f is = do x <- chooseSplit f is case x of Nothing -> do y <- fb case y of Nothing -> return Nothing Just as -> fmap (as ++) `liftM` permuteFallback fb f is Just (a, is') -> fmap (a:) `liftM` permuteFallback fb f is'