packages feed

rattletrap-10.0.0: src/lib/Rattletrap/Get.hs

module Rattletrap.Get where

import qualified Control.Applicative as Applicative

newtype Get s m a = Get (s -> m (Either String (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 = Get . const . pure . Left

instance Monad m => Applicative.Alternative (Get s m) where
  empty = fail "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 (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