{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TupleSections #-}
module Text.Pandoc.Readers.Odt.Arrows.State where
import Control.Arrow
import qualified Control.Category as Cat
import Control.Monad
import Text.Pandoc.Readers.Odt.Arrows.Utils
import Text.Pandoc.Readers.Odt.Generic.Fallible
newtype ArrowState state a b = ArrowState
{ runArrowState :: (state, a) -> (state, b) }
withState :: (state -> a -> (state, b)) -> ArrowState state a b
withState = ArrowState . uncurry
modifyState :: (state -> state ) -> ArrowState state a a
modifyState = ArrowState . first
ignoringState :: ( a -> b ) -> ArrowState state a b
ignoringState = ArrowState . second
fromState :: (state -> (state, b)) -> ArrowState state a b
fromState = ArrowState . (.fst)
extractFromState :: (state -> b ) -> ArrowState state x b
extractFromState f = ArrowState $ \(state,_) -> (state, f state)
tryModifyState :: (state -> Either f state)
-> ArrowState state a (Either f a)
tryModifyState f = ArrowState $ \(state,a)
-> (state,).Left ||| (,Right a) $ f state
instance Cat.Category (ArrowState s) where
id = ArrowState id
arrow2 . arrow1 = ArrowState $ runArrowState arrow2 . runArrowState arrow1
instance Arrow (ArrowState state) where
arr = ignoringState
first a = ArrowState $ \(s,(aF,aS))
-> second (,aS) $ runArrowState a (s,aF)
second a = ArrowState $ \(s,(aF,aS))
-> second (aF,) $ runArrowState a (s,aS)
instance ArrowChoice (ArrowState state) where
left a = ArrowState $ \(s,e) -> case e of
Left l -> second Left $ runArrowState a (s,l)
Right r -> (s, Right r)
right a = ArrowState $ \(s,e) -> case e of
Left l -> (s, Left l)
Right r -> second Right $ runArrowState a (s,r)
instance ArrowApply (ArrowState state) where
app = ArrowState $ \(s, (f,b)) -> runArrowState f (s,b)
withSubStateF :: ArrowState s x (Either f s')
-> ArrowState s' s (Either f s )
-> ArrowState s x (Either f x )
withSubStateF unlift a = keepingTheValue (withSubStateF' unlift a)
>>^ spreadChoice
>>^ fmap fst
withSubStateF' :: ArrowState s x (Either f s')
-> ArrowState s' s (Either f s )
-> ArrowState s x (Either f s')
withSubStateF' unlift a = ArrowState go
where go p@(s,_) = tryRunning unlift
( tryRunning a (second Right) )
p
where tryRunning a' b v = case runArrowState a' v of
(_ , Left f) -> (s, Left f)
(x , Right y) -> b (y,x)
foldS :: (Foldable f, Monoid m) => ArrowState s x m -> ArrowState s (f x) m
foldS a = ArrowState $ \(s,f) -> foldr a' (s,mempty) f
where a' x (s',m) = second (mappend m) $ runArrowState a (s',x)
iterateS :: (Foldable f, MonadPlus m)
=> ArrowState s x y
-> ArrowState s (f x) (m y)
iterateS a = ArrowState $ \(s,f) -> foldr a' (s,mzero) f
where a' x (s',m) = second (mplus m.return) $ runArrowState a (s',x)
iterateSL :: (Foldable f, MonadPlus m)
=> ArrowState s x y
-> ArrowState s (f x) (m y)
iterateSL a = ArrowState $ \(s,f) -> foldl a' (s,mzero) f
where a' (s',m) x = second (mplus m.return) $ runArrowState a (s',x)
iterateS' :: (Foldable f, MonadPlus m)
=> ArrowState s x (Either e y )
-> ArrowState s (f x) (Either e (m y))
iterateS' a = ArrowState $ \(s,f) -> foldr (a' s) (s,Right mzero) f
where a' s x (s',Right m) = case runArrowState a (s',x) of
(s'',Right m') -> (s'',Right $ mplus m $ return m')
(_ ,Left e ) -> (s ,Left e )
a' _ _ e = e