2020-02-23 22:24:59 +01:00
|
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
|
|
{-# LANGUAGE FunctionalDependencies #-}
|
|
|
|
{-# LANGUAGE FlexibleInstances #-}
|
|
|
|
{-# LANGUAGE FlexibleContexts #-}
|
|
|
|
{-# LANGUAGE UndecidableInstances #-}
|
|
|
|
module PDF.Box (
|
|
|
|
Box(..)
|
2020-02-25 17:36:54 +01:00
|
|
|
, I(..)
|
2020-02-24 17:27:37 +01:00
|
|
|
, (.@)
|
2020-02-25 17:36:54 +01:00
|
|
|
, at
|
2020-02-24 17:27:37 +01:00
|
|
|
, edit
|
2020-02-25 17:36:54 +01:00
|
|
|
, forAll
|
2020-02-23 22:24:59 +01:00
|
|
|
, modifyAt
|
|
|
|
) where
|
|
|
|
|
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-02-25 17:36:54 +01:00
|
|
|
import Data.Map (Map)
|
|
|
|
import qualified Data.Map as Map (insert, lookup, member)
|
|
|
|
import Prelude hiding (fail)
|
|
|
|
|
|
|
|
data I = I Int
|
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
|
|
|
|
w :: i -> a -> b -> m a
|
|
|
|
|
2020-02-24 17:27:37 +01:00
|
|
|
edit :: Box m i a b => i -> (b -> m b) -> a -> m a
|
|
|
|
edit i f a =
|
|
|
|
r i a >>= f >>= w i a
|
2020-02-23 22:24:59 +01:00
|
|
|
|
2020-02-25 17:36:54 +01:00
|
|
|
at :: (MonadState a m, Box m i a b) => i -> (b -> m c) -> m c
|
|
|
|
at i f = get >>= r i >>= f
|
|
|
|
|
2020-02-23 22:24:59 +01:00
|
|
|
modifyAt :: (MonadState a m, Box m i a b) => i -> (b -> m b) -> m ()
|
2020-02-24 17:27:37 +01:00
|
|
|
modifyAt i f = get >>= edit i f >>= put
|
2020-02-23 22:24:59 +01:00
|
|
|
|
2020-02-25 17:36:54 +01:00
|
|
|
forAll :: (MonadState a m, Box m i a (t b)) => i -> (b -> m ()) -> m ()
|
|
|
|
forAll = undefined
|
|
|
|
|
2020-02-24 17:27:37 +01:00
|
|
|
instance (Box m i a b, Box m j b c) => Box m (i, j) a c where
|
|
|
|
r (i, j) a = r i a >>= r j
|
2020-02-24 21:39:02 +01:00
|
|
|
w (i, j) a c = edit i (flip (w j) c) a
|
2020-02-24 17:27:37 +01:00
|
|
|
|
2020-02-25 17:36:54 +01:00
|
|
|
instance MonadFail m => Box m I [a] a where
|
|
|
|
r (I i) = getAt i
|
|
|
|
where
|
|
|
|
getAt _ [] = fail $ "Index out of bounds " ++ show i
|
|
|
|
getAt 0 (x:_) = return x
|
|
|
|
getAt k (_:xs) = getAt (k+1) xs
|
|
|
|
w (I i) l newX = setAt i l
|
|
|
|
where
|
|
|
|
setAt _ [] = fail $ "Index out of bounds " ++ show i
|
|
|
|
setAt 0 (_:xs) = return (newX:xs)
|
|
|
|
setAt k (x:xs) = (x:)<$>(setAt (k-1) xs)
|
|
|
|
|
|
|
|
instance (Ord k, MonadFail m) => Box m k (Map k a) a where
|
|
|
|
r k = maybe (fail "Unknown key") return . Map.lookup k
|
|
|
|
w k aMap a
|
|
|
|
| Map.member k aMap =
|
|
|
|
return $ Map.insert k a aMap
|
|
|
|
| otherwise = fail "Unknown key"
|
|
|
|
|
2020-02-24 17:27:37 +01:00
|
|
|
infixr 6 .@
|
|
|
|
(.@) :: a -> b -> (a, b)
|
|
|
|
(.@) = (,)
|