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)
|
2023-08-28 14:00:54 -04:00
|
|
|
%builtin Natural Length
|
2023-03-31 13:23:30 -04:00
|
|
|
|
|
|
|
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
|
2023-08-28 14:00:54 -04:00
|
|
|
subsetTail : Length xs => (0 x : a) -> Subset xs (x :: xs)
|
|
|
|
subsetTail _ = subsetWith S
|
2023-03-31 13:23:30 -04:00
|
|
|
|
|
|
|
|
|
|
|
export
|
2023-08-28 14:00:54 -04:00
|
|
|
catchMaybeAt : (0 lbl : tag) -> (Has (ExceptL lbl e) fs, Length fs) =>
|
|
|
|
(e -> Eff fs a) -> Eff fs a -> Eff fs a
|
|
|
|
catchMaybeAt lbl hnd act =
|
|
|
|
catchAt lbl hnd $ lift @{subsetTail $ ExceptL lbl e} act
|
2023-03-31 13:23:30 -04:00
|
|
|
|
|
|
|
export %inline
|
2023-08-28 14:00:54 -04:00
|
|
|
catchMaybe : (Has (Except e) fs, Length fs) =>
|
|
|
|
(e -> Eff fs a) -> Eff fs a -> Eff fs a
|
|
|
|
catchMaybe = catchMaybeAt ()
|
|
|
|
|
|
|
|
export
|
|
|
|
wrapErrAt : (0 lbl : tag) -> (Has (ExceptL lbl e) fs, Length fs) =>
|
|
|
|
(e -> e) -> Eff fs a -> Eff fs a
|
|
|
|
wrapErrAt lbl wrap = catchMaybeAt lbl (\ex => throwAt lbl $ wrap ex)
|
|
|
|
|
|
|
|
export %inline
|
|
|
|
wrapErr : (Has (Except e) fs, Length fs) => (e -> e) -> Eff fs a -> Eff 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
|