cassette-0.2.0: src/Text/Cassette/Internal/Tr.hs
{-# LANGUAGE BlockArguments #-}
module Text.Cassette.Internal.Tr where
import Control.Category (Category(..))
import Prelude hiding (flip, id, (.))
-- | The type of string transformers in CPS, /i.e./ functions from strings to
-- strings.
type C r = (String -> r) -> String -> r
-- | @'Tr' r r'@ is the type of string transformers with answer type
-- modification from @r@ to @r'@ through control effects.
newtype Tr r r' = Tr { unTr :: C r -> C r' }
instance Category Tr where
id = Tr id
Tr f . Tr g = Tr (f . g)
-- | '(<>)' is the choice operator. Note that this is an unrestricted
-- backtracking operator: it never commits to any particular choice.
instance Semigroup (Tr r r') where
Tr f <> Tr g = Tr \k k' s -> f k (\_ -> g k k' s) s
-- | 'mempty' is the string transformer that always fails.
instance Monoid (Tr r r') where
mempty = Tr \_ k' s -> k' s
-- | Capture continuation up to the closest 'reset'.
shift :: (C r -> Tr w r') -> Tr r r'
shift f = Tr \k -> unTr (f k) id
-- | Inverse of 'shift'.
plug :: C r -> Tr r r' -> Tr w r'
plug k (Tr f) = Tr \_ -> f k
-- | Replace the success continuation.
replace :: C r -> Tr w r
replace k = plug k id
pushNeg :: a -> Tr (a -> r) r
pushNeg x = shift \k -> replace \k' s -> k (\s _ -> k' s) s x
popNeg :: Tr r (a -> r)
popNeg = shift \k -> replace \k' s x -> k (\s -> k' s x) s
pushPos :: a -> Tr (r -> r') ((a -> r) -> r')
pushPos x = shift \k -> replace \k' s u -> k (\s _ -> k' s u) s (u x)
popPos :: Tr ((a -> r) -> r') (r -> r')
popPos = shift \k -> replace \k' s u -> k (\s _ -> k' s u) s (\_ -> u)