module Mit.Monad
( Mit,
runMit,
io,
getEnv,
withEnv,
Goto,
Label,
label,
with,
with_,
X,
)
where
import Control.Monad qualified
import Mit.Prelude
newtype Mit r x a
= Mit (r -> (a -> IO x) -> IO x)
deriving stock (Functor)
instance Applicative (Mit r x) where
pure x = Mit \_ k -> k x
(<*>) = ap
instance Monad (Mit r x) where
return = pure
Mit mx >>= f =
Mit \r k ->
mx r (\a -> unMit (f a) r k)
instance MonadIO (Mit r x) where
liftIO = io
unMit :: Mit r x a -> r -> (a -> IO x) -> IO x
unMit (Mit k) =
k
runMit :: r -> Mit r a a -> IO a
runMit r m =
unMit m r pure
return :: x -> Mit r x a
return x =
Mit \_ _ -> pure x
io :: IO a -> Mit r x a
io m =
Mit \_ k -> do
x <- m
k x
getEnv :: Mit r x r
getEnv =
Mit \r k -> k r
withEnv :: (r -> s) -> Mit s x a -> Mit r x a
withEnv f m =
Mit \r k -> unMit m (f r) k
type Goto r x a =
forall xx void. Label (X x a) xx => a -> Mit r xx void
label :: forall r x a. (Goto r x a -> Mit r (X x a) a) -> Mit r x a
label f =
Mit \r k -> do
unX k (unMit (f \a -> return (bury @(X x a) (XR a))) r (pure . XR))
with :: (forall v. (a -> IO v) -> IO v) -> (a -> Mit r (X x b) b) -> Mit r x b
with f action =
Mit \r k ->
unX k (f \a -> unMit (action a) r (pure . XR))
with_ :: (forall v. IO v -> IO v) -> Mit r (X x a) a -> Mit r x a
with_ f action =
Mit \r k ->
unX k (f (unMit action r (pure . XR)))
-- instance Label (X a b) (X a b)
-- instance Label (X a b) (X (X a b) c)
-- instance Label (X a b) (X (X (X a b) c) d)
-- etc...
data X a b
= XL a
| XR b
unX :: (a -> IO b) -> IO (X b a) -> IO b
unX k mx =
mx >>= \case
XL b -> pure b
XR a -> k a
class Label a b where
bury :: a -> b
default bury :: a ~ b => a -> b
bury = id
-- FIXME I don't really think this is correct...
instance {-# INCOHERENT #-} Label (X a b) (X a b)
instance Label (X a b) (X c d) => Label (X a b) (X (X c d) e) where
bury = XL . bury