-- |
-- Alternative utilities.
-- For instance, they can be applied with parsing libraries.
module VectorBuilder.Alternative where

import Data.Vector (Vector)
import qualified Data.Vector.Generic as C
import qualified VectorBuilder.Builder as A
import VectorBuilder.Prelude hiding (many, some)
import qualified VectorBuilder.Vector as B

{-# INLINEABLE many #-}
many :: (Alternative m, C.Vector vector a) => m a -> m (vector a)
many :: m a -> m (vector a)
many = (Builder a -> vector a) -> m (Builder a) -> m (vector a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Builder a -> vector a
forall (vector :: * -> *) element.
Vector vector element =>
Builder element -> vector element
B.build (m (Builder a) -> m (vector a))
-> (m a -> m (Builder a)) -> m a -> m (vector a)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. m a -> m (Builder a)
forall (m :: * -> *) a. Alternative m => m a -> m (Builder a)
manyBuilder

{-# INLINEABLE manyBuilder #-}
manyBuilder :: Alternative m => m a -> m (A.Builder a)
manyBuilder :: m a -> m (Builder a)
manyBuilder m a
m =
  let loop :: m (Builder a)
loop = (Builder a -> Builder a -> Builder a
forall a. Semigroup a => a -> a -> a
(<>) (Builder a -> Builder a -> Builder a)
-> (a -> Builder a) -> a -> Builder a -> Builder a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Builder a
forall element. element -> Builder element
A.singleton (a -> Builder a -> Builder a) -> m a -> m (Builder a -> Builder a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m a
m m (Builder a -> Builder a) -> m (Builder a) -> m (Builder a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m (Builder a)
loop) m (Builder a) -> m (Builder a) -> m (Builder a)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Builder a -> m (Builder a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Builder a
forall a. Monoid a => a
mempty
   in m (Builder a)
loop

{-# INLINEABLE some #-}
some :: (Alternative m, C.Vector vector a) => m a -> m (vector a)
some :: m a -> m (vector a)
some m a
m = Builder a -> vector a
forall (vector :: * -> *) element.
Vector vector element =>
Builder element -> vector element
B.build (Builder a -> vector a) -> m (Builder a) -> m (vector a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m a -> m (Builder a)
forall (m :: * -> *) a. Alternative m => m a -> m (Builder a)
someBuilder m a
m

{-# INLINEABLE someBuilder #-}
someBuilder :: Alternative m => m a -> m (A.Builder a)
someBuilder :: m a -> m (Builder a)
someBuilder m a
m = Builder a -> Builder a -> Builder a
forall a. Semigroup a => a -> a -> a
(<>) (Builder a -> Builder a -> Builder a)
-> (a -> Builder a) -> a -> Builder a -> Builder a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Builder a
forall element. element -> Builder element
A.singleton (a -> Builder a -> Builder a) -> m a -> m (Builder a -> Builder a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m a
m m (Builder a -> Builder a) -> m (Builder a) -> m (Builder a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m a -> m (Builder a)
forall (m :: * -> *) a. Alternative m => m a -> m (Builder a)
manyBuilder m a
m