module Effectful.Zoo.Core.Function
  ( once,
  ) where

import Effectful
import Effectful.Concurrent
import Effectful.Concurrent.MVar
import Effectful.Zoo.Core.Prim
import HaskellWorks.Prelude

once :: ()
  => r <: Concurrent
  => Eff r a
  -> Eff r (Eff r a)
once :: forall (r :: [Effect]) a.
(r <: Concurrent) =>
Eff r a -> Eff r (Eff r a)
once Eff r a
f = do
  MVar (Maybe a)
cache <- Maybe a -> Eff r (MVar (Maybe a))
forall (es :: [Effect]) a.
(Concurrent :> es) =>
a -> Eff es (MVar a)
newMVar Maybe a
forall a. Maybe a
Nothing
  return $ do
    Maybe a
resultOrRunning <- MVar (Maybe a) -> Eff r (Maybe a)
forall (es :: [Effect]) a. (Concurrent :> es) => MVar a -> Eff es a
takeMVar MVar (Maybe a)
cache
    case Maybe a
resultOrRunning of
      Just a
result -> do
        MVar (Maybe a) -> Maybe a -> Eff r ()
forall (es :: [Effect]) a.
(Concurrent :> es) =>
MVar a -> a -> Eff es ()
putMVar MVar (Maybe a)
cache (a -> Maybe a
forall a. a -> Maybe a
Just a
result)
        return a
result
      Maybe a
Nothing -> do
        a
result <- Eff r a
f
        MVar (Maybe a) -> Maybe a -> Eff r ()
forall (es :: [Effect]) a.
(Concurrent :> es) =>
MVar a -> a -> Eff es ()
putMVar MVar (Maybe a)
cache (a -> Maybe a
forall a. a -> Maybe a
Just a
result)
        return a
result