module Control.Monad.Schedule.Yield where

-- base
import qualified Control.Concurrent as Concurrent
import Control.Monad.IO.Class
import Data.Functor.Identity (Identity (runIdentity))

-- monad-schedule
import Control.Monad.Schedule.Class
import Control.Monad.Schedule.Trans

-- * 'YieldT'

-- | A monad for scheduling with cooperative concurrency.
type YieldT = ScheduleT ()

type Yield = YieldT Identity

-- | Let another thread wake up.
yield :: (Monad m) => YieldT m ()
yield :: forall (m :: * -> *). Monad m => YieldT m ()
yield = () -> ScheduleT () m ()
forall (m :: * -> *) diff. Monad m => diff -> ScheduleT diff m ()
wait ()

runYieldT :: (Monad m) => YieldT m a -> m a
runYieldT :: forall (m :: * -> *) a. Monad m => YieldT m a -> m a
runYieldT = (() -> m ()) -> ScheduleT () m a -> m a
forall (m :: * -> *) diff a.
Monad m =>
(diff -> m ()) -> ScheduleT diff m a -> m a
runScheduleT ((() -> m ()) -> ScheduleT () m a -> m a)
-> (() -> m ()) -> ScheduleT () m a -> m a
forall a b. (a -> b) -> a -> b
$ m () -> () -> m ()
forall a b. a -> b -> a
const (m () -> () -> m ()) -> m () -> () -> m ()
forall a b. (a -> b) -> a -> b
$ () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

runYield :: Yield a -> a
runYield :: forall a. Yield a -> a
runYield = Identity a -> a
forall a. Identity a -> a
runIdentity (Identity a -> a) -> (Yield a -> Identity a) -> Yield a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Yield a -> Identity a
forall (m :: * -> *) a. Monad m => YieldT m a -> m a
runYieldT

{- | Run a 'YieldT' value in a 'MonadIO',
  interpreting 'yield's as GHC concurrency yields.
-}
runYieldIO ::
  (MonadIO m) =>
  YieldT m a ->
  m a
runYieldIO :: forall (m :: * -> *) a. MonadIO m => YieldT m a -> m a
runYieldIO = (() -> m ()) -> ScheduleT () m a -> m a
forall (m :: * -> *) diff a.
Monad m =>
(diff -> m ()) -> ScheduleT diff m a -> m a
runScheduleT ((() -> m ()) -> ScheduleT () m a -> m a)
-> (() -> m ()) -> ScheduleT () m a -> m a
forall a b. (a -> b) -> a -> b
$ m () -> () -> m ()
forall a b. a -> b -> a
const (m () -> () -> m ()) -> m () -> () -> m ()
forall a b. (a -> b) -> a -> b
$ IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ()
Concurrent.yield