2020-02-23 22:24:59 +01:00
|
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
|
|
{-# LANGUAGE FunctionalDependencies #-}
|
|
|
|
{-# LANGUAGE FlexibleInstances #-}
|
|
|
|
{-# LANGUAGE FlexibleContexts #-}
|
|
|
|
{-# LANGUAGE UndecidableInstances #-}
|
2020-02-27 17:22:12 +01:00
|
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
2020-02-23 22:24:59 +01:00
|
|
|
module PDF.Box (
|
|
|
|
Box(..)
|
2020-02-27 17:22:12 +01:00
|
|
|
, Index(..)
|
|
|
|
, Maybe_(..)
|
|
|
|
, Either_(..)
|
2020-02-25 17:36:54 +01:00
|
|
|
, at
|
2020-02-26 17:14:43 +01:00
|
|
|
, atAll
|
2020-02-24 17:27:37 +01:00
|
|
|
, edit
|
2020-02-23 22:24:59 +01:00
|
|
|
) where
|
|
|
|
|
2020-02-27 17:22:12 +01:00
|
|
|
import Control.Monad.Except (ExceptT(..), runExceptT)
|
2020-02-25 17:36:54 +01:00
|
|
|
import Control.Monad.Fail (MonadFail(..))
|
2020-02-23 22:24:59 +01:00
|
|
|
import Control.Monad.State (MonadState(..))
|
2020-03-03 18:16:49 +01:00
|
|
|
--import Control.Monad.Reader (MonadReader(..))
|
2020-02-25 17:36:54 +01:00
|
|
|
import Data.Map (Map)
|
|
|
|
import qualified Data.Map as Map (insert, lookup, member)
|
2020-03-11 18:52:09 +01:00
|
|
|
import Data.OrderedMap (OrderedMap)
|
|
|
|
import qualified Data.OrderedMap as OrderedMap (lookup, set)
|
2020-02-25 17:36:54 +01:00
|
|
|
import Prelude hiding (fail)
|
|
|
|
|
2020-03-03 18:16:49 +01:00
|
|
|
{-
|
|
|
|
instance (Monad m, MonadState s m) => MonadReader s m where
|
|
|
|
ask = get
|
|
|
|
local f m = do
|
|
|
|
backup <- get
|
|
|
|
put $ f backup
|
|
|
|
result <- m
|
|
|
|
put backup
|
|
|
|
return result
|
|
|
|
-}
|
|
|
|
|
2020-02-27 17:22:12 +01:00
|
|
|
newtype Index = Index Int
|
|
|
|
newtype Maybe_ x = Maybe_ x
|
|
|
|
newtype Either_ b x = Either_ x
|
2020-02-23 22:24:59 +01:00
|
|
|
|
2020-02-24 17:27:37 +01:00
|
|
|
class Monad m => Box m i a b | m a i -> b where
|
2020-02-23 22:24:59 +01:00
|
|
|
r :: i -> a -> m b
|
2020-02-26 17:14:43 +01:00
|
|
|
w :: i -> b -> a -> m a
|
2020-02-23 22:24:59 +01:00
|
|
|
|
2020-02-26 17:14:43 +01:00
|
|
|
at :: Box m i a b => i -> (b -> m b) -> a -> m a
|
|
|
|
at i f a = r i a >>= f >>= flip (w i) a
|
2020-02-23 22:24:59 +01:00
|
|
|
|
2020-02-26 17:14:43 +01:00
|
|
|
atAll :: (Traversable t, Monad m, Box m i a (t b)) => i -> (b -> m b) -> a -> m a
|
|
|
|
atAll i f = at i $ (mapM f)
|
2020-02-25 17:36:54 +01:00
|
|
|
|
2020-02-26 17:14:43 +01:00
|
|
|
edit :: MonadState a m => (a -> m a) -> m ()
|
|
|
|
edit f = get >>= f >>= put
|
2020-02-24 17:27:37 +01:00
|
|
|
|
2020-02-27 17:22:12 +01:00
|
|
|
instance MonadFail m => Box m Index [a] a where
|
|
|
|
r (Index i) [] = fail $ "Index out of bounds " ++ show i
|
|
|
|
r (Index 0) (x:_) = return x
|
|
|
|
r (Index i) (_:xs) = r (Index (i-1)) xs
|
|
|
|
|
|
|
|
w (Index i) _ [] = fail $ "Index out of bounds " ++ show i
|
|
|
|
w (Index 0) newX (_:xs) = return (newX:xs)
|
|
|
|
w (Index i) newX (x:xs) = (x:) <$> w (Index (i-1)) newX xs
|
2020-02-25 17:36:54 +01:00
|
|
|
|
|
|
|
instance (Ord k, MonadFail m) => Box m k (Map k a) a where
|
|
|
|
r k = maybe (fail "Unknown key") return . Map.lookup k
|
2020-02-26 17:14:43 +01:00
|
|
|
w k a aMap
|
2020-02-25 17:36:54 +01:00
|
|
|
| Map.member k aMap =
|
|
|
|
return $ Map.insert k a aMap
|
|
|
|
| otherwise = fail "Unknown key"
|
2020-02-27 17:22:12 +01:00
|
|
|
|
2020-03-11 18:52:09 +01:00
|
|
|
instance (Ord k, MonadFail m) => Box m k (OrderedMap k a) a where
|
|
|
|
r k = maybe (fail "Unknown key") return . OrderedMap.lookup k
|
|
|
|
w k a orderedMap = r k orderedMap >> return (OrderedMap.set k a orderedMap)
|
|
|
|
|
2020-02-27 17:22:12 +01:00
|
|
|
instance (Monad m, Box Maybe i a b) => Box m (Maybe_ i) a (Maybe b) where
|
|
|
|
r (Maybe_ i) = return . r i
|
|
|
|
w (Maybe_ i) (Just b) a =
|
|
|
|
return . maybe a id $ w i b a
|
|
|
|
w _ _ obj = return obj
|
|
|
|
|
|
|
|
instance (Monad m, Box (ExceptT e m) i a b) => Box m (Either_ e i) a (Either e b) where
|
|
|
|
r (Either_ i) a = runExceptT (r i a)
|
|
|
|
w (Either_ i) (Right b) a =
|
|
|
|
either (const a) id <$> runExceptT (w i b a :: ExceptT e m a)
|
|
|
|
w _ _ a = return a
|