2023-03-31 13:23:30 -04:00
|
|
|
module Quox.EffExtra
|
|
|
|
|
|
|
|
import public Control.Eff
|
|
|
|
|
2023-08-25 12:09:06 -04:00
|
|
|
import Quox.ST
|
2023-03-31 13:23:30 -04:00
|
|
|
import Data.IORef
|
|
|
|
|
|
|
|
|
|
|
|
export
|
|
|
|
localAt : (0 lbl : tag) -> Has (StateL lbl s) fs =>
|
|
|
|
(s -> s) -> Eff fs a -> Eff fs a
|
|
|
|
localAt lbl f act = do
|
|
|
|
old <- getAt lbl
|
|
|
|
modifyAt lbl f *> act <* putAt lbl old
|
|
|
|
|
|
|
|
export %inline
|
|
|
|
localAt_ : (0 lbl : tag) -> Has (StateL lbl s) fs =>
|
|
|
|
s -> Eff fs a -> Eff fs a
|
|
|
|
localAt_ lbl x = localAt lbl $ const x
|
|
|
|
|
|
|
|
export %inline
|
|
|
|
local : Has (State s) fs => (s -> s) -> Eff fs a -> Eff fs a
|
|
|
|
local = localAt ()
|
|
|
|
|
|
|
|
export %inline
|
|
|
|
local_ : Has (State s) fs => s -> Eff fs a -> Eff fs a
|
|
|
|
local_ = localAt_ ()
|
|
|
|
|
|
|
|
|
2023-08-27 12:59:16 -04:00
|
|
|
export %inline
|
|
|
|
getsAt : (0 lbl : tag) -> Has (StateL lbl s) fs => (s -> a) -> Eff fs a
|
|
|
|
getsAt lbl f = f <$> getAt lbl
|
|
|
|
|
|
|
|
export %inline
|
|
|
|
gets : Has (State s) fs => (s -> a) -> Eff fs a
|
|
|
|
gets = getsAt ()
|
|
|
|
|
|
|
|
|
2023-03-31 13:23:30 -04:00
|
|
|
export
|
2023-08-25 12:09:06 -04:00
|
|
|
handleStateIORef : HasIO m => IORef st -> StateL lbl st a -> m a
|
|
|
|
handleStateIORef r Get = readIORef r
|
|
|
|
handleStateIORef r (Put s) = writeIORef r s
|
2023-03-31 13:23:30 -04:00
|
|
|
|
|
|
|
export
|
2023-08-25 12:09:06 -04:00
|
|
|
handleStateSTRef : HasST m => STRef s st -> StateL lbl st a -> m s a
|
|
|
|
handleStateSTRef r Get = readRef r
|
|
|
|
handleStateSTRef r (Put s) = writeRef r s
|
2023-03-31 13:23:30 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public export
|
|
|
|
data Length : List a -> Type where
|
|
|
|
Z : Length []
|
|
|
|
S : Length xs -> Length (x :: xs)
|
|
|
|
|
|
|
|
export
|
|
|
|
subsetWith : Length xs => (forall z. Has z xs -> Has z ys) ->
|
|
|
|
Subset xs ys
|
|
|
|
subsetWith @{Z} f = []
|
|
|
|
subsetWith @{S len} f = f Z :: subsetWith (f . S)
|
|
|
|
|
|
|
|
export
|
|
|
|
subsetSelf : Length xs => Subset xs xs
|
|
|
|
subsetSelf = subsetWith id
|
|
|
|
|
|
|
|
export
|
|
|
|
subsetTail : Length xs => Subset xs (x :: xs)
|
|
|
|
subsetTail = subsetWith S
|
|
|
|
|
|
|
|
|
|
|
|
-- [fixme] allow the error to be anywhere in the effect list
|
|
|
|
export
|
2023-08-25 12:09:06 -04:00
|
|
|
wrapErrAt : Length fs => (0 lbl : tag) -> (e -> e') ->
|
|
|
|
Eff (ExceptL lbl e :: fs) a -> Eff (ExceptL lbl e' :: fs) a
|
2023-03-31 13:23:30 -04:00
|
|
|
wrapErrAt lbl f act =
|
|
|
|
rethrowAt lbl . mapFst f =<< lift @{subsetTail} (runExceptAt lbl act)
|
|
|
|
|
|
|
|
export %inline
|
2023-08-25 12:09:06 -04:00
|
|
|
wrapErr : Length fs => (e -> e') ->
|
|
|
|
Eff (Except e :: fs) a -> Eff (Except e' :: fs) a
|
2023-03-31 13:23:30 -04:00
|
|
|
wrapErr = wrapErrAt ()
|
|
|
|
|
|
|
|
|
2023-08-25 12:09:06 -04:00
|
|
|
export
|
|
|
|
handleExcept : Functor m => (forall c. e -> m c) -> ExceptL lbl e a -> m a
|
|
|
|
handleExcept thr (Err e) = thr e
|
|
|
|
|
|
|
|
|
|
|
|
export
|
|
|
|
handleReaderConst : Applicative m => r -> ReaderL lbl r a -> m a
|
|
|
|
handleReaderConst x Ask = pure x
|
|
|
|
|
|
|
|
|
|
|
|
public export
|
|
|
|
record IOErr e a where
|
|
|
|
constructor IOE
|
|
|
|
fromIOErr : IO (Either e a)
|
|
|
|
|
|
|
|
export
|
|
|
|
Functor (IOErr e) where
|
|
|
|
map f (IOE e) = IOE $ map f <$> e
|
|
|
|
|
|
|
|
export
|
|
|
|
Applicative (IOErr e) where
|
|
|
|
pure x = IOE $ pure $ pure x
|
|
|
|
IOE f <*> IOE x = IOE [|f <*> x|]
|
|
|
|
|
|
|
|
export
|
|
|
|
Monad (IOErr e) where
|
|
|
|
IOE m >>= k = IOE $ do
|
|
|
|
case !m of
|
|
|
|
Left err => pure $ Left err
|
|
|
|
Right x => fromIOErr $ k x
|
|
|
|
|
|
|
|
export
|
|
|
|
MonadRec (IOErr e) where
|
|
|
|
tailRecM s (Access r) x k = IOE $ do
|
|
|
|
let IOE m = k s x
|
|
|
|
case !m of
|
|
|
|
Left err => pure $ Left err
|
|
|
|
Right (Cont s' p y) => fromIOErr $ tailRecM s' (r s' p) y k
|
|
|
|
Right (Done y) => pure $ Right y
|
|
|
|
|
|
|
|
export
|
|
|
|
HasIO (IOErr e) where
|
|
|
|
liftIO = IOE . map Right
|
|
|
|
|
2023-03-31 13:23:30 -04:00
|
|
|
export %inline
|
2023-08-25 12:09:06 -04:00
|
|
|
ioLeft : e -> IOErr e a
|
|
|
|
ioLeft = IOE . pure . Left
|