module Mit.Monad
( Mit,
runMit,
io,
getEnv,
withEnv,
Goto,
label,
with,
with_,
)
where
import Control.Monad qualified
import Data.Unique
import Mit.Prelude
import Unsafe.Coerce (unsafeCoerce)
newtype Mit r a
= Mit (forall x. r -> (a -> IO x) -> IO x)
deriving stock (Functor)
instance Applicative (Mit r) where
pure x = Mit \_ k -> k x
(<*>) = ap
instance Monad (Mit r) where
return = pure
Mit mx >>= f =
Mit \r k ->
mx r (\a -> unMit (f a) r k)
instance MonadIO (Mit r) where
liftIO = io
unMit :: Mit r a -> r -> (a -> IO x) -> IO x
unMit (Mit k) =
k
runMit :: r -> Mit r a -> IO a
runMit r m =
unMit m r pure
io :: IO a -> Mit r a
io m =
Mit \_ k -> do
x <- m
k x
getEnv :: Mit r r
getEnv =
Mit \r k -> k r
withEnv :: (r -> s) -> Mit s a -> Mit r a
withEnv f m =
Mit \r k -> unMit m (f r) k
type Goto r a =
forall void. a -> Mit r void
label :: (Goto r a -> Mit r a) -> Mit r a
label f =
Mit \r k -> do
n <- newUnique
try (runMit r (f (\x -> io (throwIO (X n x))))) >>= \case
Left err@(X m y)
| n == m -> k (unsafeCoerce y)
| otherwise -> throwIO err
Right x -> k x
data X = forall a. X Unique a
instance Exception X where
toException = asyncExceptionToException
fromException = asyncExceptionFromException
instance Show X where
show _ = ""
with :: (forall v. (a -> IO v) -> IO v) -> (a -> Mit r b) -> Mit r b
with f action =
Mit \r k -> do
b <- f (\a -> runMit r (action a))
k b
with_ :: (forall v. IO v -> IO v) -> Mit r a -> Mit r a
with_ f action =
Mit \r k -> do
a <- f (runMit r action)
k a