{-# LANGUAGE TemplateHaskell #-}

-- | Something for converting polysemy actions into IO actions
module Calamity.Internal.RunIntoIO
    ( runSemToIO
    , bindSemToIO ) where

import           Data.Functor

import qualified Polysemy                         as P
import qualified Polysemy.Final                   as P

runSemToIO :: forall r a. P.Member (P.Final IO) r => P.Sem r a -> P.Sem r (IO (Maybe a))
runSemToIO :: forall (r :: EffectRow) a.
Member (Final IO) r =>
Sem r a -> Sem r (IO (Maybe a))
runSemToIO Sem r a
m = forall (m :: * -> *) (r :: EffectRow) a.
Member (Final m) r =>
Strategic m (Sem r) a -> Sem r a
P.withStrategicToFinal forall a b. (a -> b) -> a -> b
$ do
  IO (f a)
m' <- forall (n :: * -> *) a (m :: * -> *) (f :: * -> *).
n a -> Sem (WithStrategy m f n) (m (f a))
P.runS Sem r a
m
  Inspector f
ins <- forall (m :: * -> *) (f :: * -> *) (n :: * -> *).
Sem (WithStrategy m f n) (Inspector f)
P.getInspectorS
  forall (m :: * -> *) a (n :: * -> *).
Functor m =>
m a -> Strategic m n a
P.liftS forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall (f :: * -> *). Inspector f -> forall x. f x -> Maybe x
P.inspect Inspector f
ins forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (f a)
m')

bindSemToIO :: forall r p a. P.Member (P.Final IO) r => (p -> P.Sem r a) -> P.Sem r (p -> IO (Maybe a))
bindSemToIO :: forall (r :: EffectRow) p a.
Member (Final IO) r =>
(p -> Sem r a) -> Sem r (p -> IO (Maybe a))
bindSemToIO p -> Sem r a
m = forall (m :: * -> *) (r :: EffectRow) a.
Member (Final m) r =>
Strategic m (Sem r) a -> Sem r a
P.withStrategicToFinal forall a b. (a -> b) -> a -> b
$ do
  f ()
istate <- forall (m :: * -> *) (f :: * -> *) (n :: * -> *).
Sem (WithStrategy m f n) (f ())
P.getInitialStateS
  f p -> IO (f a)
m' <- forall a (n :: * -> *) b (m :: * -> *) (f :: * -> *).
(a -> n b) -> Sem (WithStrategy m f n) (f a -> m (f b))
P.bindS p -> Sem r a
m
  Inspector f
ins <- forall (m :: * -> *) (f :: * -> *) (n :: * -> *).
Sem (WithStrategy m f n) (Inspector f)
P.getInspectorS
  forall (m :: * -> *) a (n :: * -> *).
Functor m =>
m a -> Strategic m n a
P.liftS forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure (\p
x -> forall (f :: * -> *). Inspector f -> forall x. f x -> Maybe x
P.inspect Inspector f
ins forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f p -> IO (f a)
m' (f ()
istate forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> p
x))