rattletrap-14.1.4: src/lib/Rattletrap/Get.hs
module Rattletrap.Get where
import qualified Control.Applicative as Applicative
import qualified Control.Exception as Exception
import qualified Data.Bifunctor as Bifunctor
import qualified Rattletrap.Exception.Empty as Empty
import qualified Rattletrap.Exception.Fail as Fail
newtype Get s m a = Get (s -> m (Either ([String], Exception.SomeException) (s, a)))
instance (Functor m) => Functor (Get s m) where
fmap f g = Get $ fmap (fmap (fmap f)) . run g
instance (Monad m) => Applicative (Get s m) where
pure x = Get $ \s -> pure $ Right (s, x)
gf <*> gx = Get $ \s1 -> do
r <- run gf s1
case r of
Left e -> pure $ Left e
Right (s2, f) -> run (fmap f gx) s2
instance (Monad m) => Monad (Get s m) where
g >>= f = Get $ \s1 -> do
r <- run g s1
case r of
Left e -> pure $ Left e
Right (s2, x) -> run (f x) s2
instance (Monad m) => MonadFail (Get s m) where
fail = throw . Fail.Fail
instance (Monad m) => Applicative.Alternative (Get s m) where
empty = throw Empty.Empty
gx <|> gy = Get $ \s -> do
r <- run gx s
case r of
Left _ -> run gy s
Right x -> pure $ Right x
run :: Get s m a -> s -> m (Either ([String], Exception.SomeException) (s, a))
run (Get f) = f
get :: (Applicative m) => Get s m s
get = Get $ \s -> pure $ Right (s, s)
put :: (Applicative m) => s -> Get s m ()
put s = Get $ \_ -> pure $ Right (s, ())
lift :: (Functor m) => m a -> Get s m a
lift m = Get $ \s -> fmap (\x -> Right (s, x)) m
throw :: (Exception.Exception e, Applicative m) => e -> Get s m a
throw = Get . const . pure . Left . (,) [] . Exception.toException
embed :: (Monad m) => Get s m a -> s -> Get t m a
embed g s = do
r <- lift $ run g s
case r of
Left (ls, e) -> labels ls $ throw e
Right (_, x) -> pure x
labels :: (Functor m) => [String] -> Get s m a -> Get s m a
labels ls g = Get $ fmap (Bifunctor.first $ Bifunctor.first (ls <>)) . run g
label :: (Functor m) => String -> Get s m a -> Get s m a
label = labels . pure