packages feed

heftia-effects-0.6.0.0: src/Control/Monad/Hefty/Concurrent/Timer.hs

-- SPDX-License-Identifier: MPL-2.0

{- |
Copyright   :  (c) 2024 Sayo contributors
License     :  MPL-2.0 (see the LICENSE file)
Maintainer  :  ymdfield@outlook.jp

Interpreters for the [Timer]("Data.Effect.Concurrent.Timer") effects.
-}
module Control.Monad.Hefty.Concurrent.Timer (
    module Control.Monad.Hefty.Concurrent.Timer,
    module Data.Effect.Concurrent.Timer,
)
where

import Control.Monad.Hefty (
    Eff,
    FOEs,
    interpret,
    raise,
    raiseUnder,
    (&),
    (:>),
 )
import Control.Monad.Hefty.Coroutine (runCoroutine)
import Control.Monad.Hefty.State (evalState)
import Data.Effect.Concurrent.Timer
import Data.Effect.Coroutine (Status (Continue, Done))
import Data.Effect.State (get, put)
import Data.Time (DiffTime)
import Data.Void (Void, absurd)

runCyclicTimer
    :: forall a es
     . (Timer :> es, FOEs es)
    => Eff (CyclicTimer ': es) a
    -> Eff es a
runCyclicTimer a = do
    timer0 :: Status (Eff es) () DiffTime Void <- runCoroutine cyclicTimer
    a
        & raiseUnder
        & interpret \case
            Wait delta ->
                get @(Status (Eff es) () DiffTime Void) >>= \case
                    Done x -> absurd x
                    Continue () k -> put =<< raise (k delta)
        & evalState timer0