{-# LANGUAGE BlockArguments #-} {-# OPTIONS_GHC -Wall -fno-warn-tabs #-} module Data.Parse (Parse, parse, unparse, (>>!)) where import Control.Applicative (empty) import Control.Monad ((>=>)) import Control.Monad.StateT (StateT(..)) type Parse s = StateT s Maybe parse :: (s -> Maybe (a, s)) -> Parse s a parse = StateT unparse :: Parse s a -> s -> Maybe (a, s) unparse = runStateT (>>!) :: Parse s a -> Parse s b -> Parse s a p >>! nla = parse $ unparse p >=> \r@(_, s) -> maybe (pure r) (const empty) $ nla `unparse` s