{-# LANGUAGE BangPatterns, GeneralizedNewtypeDeriving, TemplateHaskell, Trustworthy #-}
module Polysemy.Fresh
(
Fresh(..)
, fresh
, freshToIO
, runFreshEnumUnsafe
, runFreshUnsafePerformIO
) where
import Data.Unique
import Polysemy.Internal
import Polysemy.Internal.Union
import System.IO.Unsafe (unsafePerformIO)
import Polysemy
import Polysemy.State
data Fresh uniq m a where
Fresh :: Fresh uniq m uniq
makeSem ''Fresh
freshToIO :: Member (Embed IO) r
=> Sem (Fresh Unique ': r) a
-> Sem r a
freshToIO :: Sem (Fresh Unique : r) a -> Sem r a
freshToIO = (forall (rInitial :: EffectRow) x.
Fresh Unique (Sem rInitial) x -> Sem r x)
-> Sem (Fresh Unique : r) a -> Sem r a
forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
FirstOrder e "interpret" =>
(forall (rInitial :: EffectRow) x. e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret ((forall (rInitial :: EffectRow) x.
Fresh Unique (Sem rInitial) x -> Sem r x)
-> Sem (Fresh Unique : r) a -> Sem r a)
-> (forall (rInitial :: EffectRow) x.
Fresh Unique (Sem rInitial) x -> Sem r x)
-> Sem (Fresh Unique : r) a
-> Sem r a
forall a b. (a -> b) -> a -> b
$ \Fresh Unique (Sem rInitial) x
Fresh -> IO Unique -> Sem r Unique
forall (m :: * -> *) (r :: EffectRow) a.
Member (Embed m) r =>
m a -> Sem r a
embed IO Unique
newUnique
{-# INLINE freshToIO #-}
runFreshEnumUnsafe :: forall n a r
. Enum n
=> Sem (Fresh n ': r) a
-> Sem r a
runFreshEnumUnsafe :: Sem (Fresh n : r) a -> Sem r a
runFreshEnumUnsafe =
(((n, a) -> a) -> Sem r (n, a) -> Sem r a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (n, a) -> a
forall a b. (a, b) -> b
snd (Sem r (n, a) -> Sem r a)
-> (Sem (Fresh n : r) a -> Sem r (n, a))
-> Sem (Fresh n : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.)
((Sem (Fresh n : r) a -> Sem r (n, a))
-> Sem (Fresh n : r) a -> Sem r a)
-> (Sem (Fresh n : r) a -> Sem r (n, a))
-> Sem (Fresh n : r) a
-> Sem r a
forall a b. (a -> b) -> a -> b
$ (n -> Sem (State n : r) a -> Sem r (n, a)
forall s (r :: EffectRow) a.
s -> Sem (State s : r) a -> Sem r (s, a)
runState @n (Int -> n
forall a. Enum a => Int -> a
toEnum Int
0) (Sem (State n : r) a -> Sem r (n, a))
-> (Sem (Fresh n : r) a -> Sem (State n : r) a)
-> Sem (Fresh n : r) a
-> Sem r (n, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.)
((Sem (Fresh n : r) a -> Sem (State n : r) a)
-> Sem (Fresh n : r) a -> Sem r (n, a))
-> (Sem (Fresh n : r) a -> Sem (State n : r) a)
-> Sem (Fresh n : r) a
-> Sem r (n, a)
forall a b. (a -> b) -> a -> b
$ (forall (rInitial :: EffectRow) x.
Fresh n (Sem rInitial) x -> Sem (State n : r) x)
-> Sem (Fresh n : r) a -> Sem (State n : r) a
forall (e1 :: (* -> *) -> * -> *) (e2 :: (* -> *) -> * -> *)
(r :: EffectRow) a.
FirstOrder e1 "reinterpret" =>
(forall (rInitial :: EffectRow) x.
e1 (Sem rInitial) x -> Sem (e2 : r) x)
-> Sem (e1 : r) a -> Sem (e2 : r) a
reinterpret
((forall (rInitial :: EffectRow) x.
Fresh n (Sem rInitial) x -> Sem (State n : r) x)
-> Sem (Fresh n : r) a -> Sem (State n : r) a)
-> (forall (rInitial :: EffectRow) x.
Fresh n (Sem rInitial) x -> Sem (State n : r) x)
-> Sem (Fresh n : r) a
-> Sem (State n : r) a
forall a b. (a -> b) -> a -> b
$ \Fresh n (Sem rInitial) x
Fresh -> do
x
s <- Sem (State n : r) x
forall s (r :: EffectRow). Member (State s) r => Sem r s
get
x -> Sem (State n : r) ()
forall s (r :: EffectRow). Member (State s) r => s -> Sem r ()
put (x -> Sem (State n : r) ()) -> x -> Sem (State n : r) ()
forall a b. (a -> b) -> a -> b
$! x -> x
forall a. Enum a => a -> a
succ x
s
x -> Sem (State n : r) x
forall (m :: * -> *) a. Monad m => a -> m a
return x
s
{-# INLINE runFreshEnumUnsafe #-}
runFreshUnsafePerformIO :: Sem (Fresh Unique ': r) a
-> Sem r a
runFreshUnsafePerformIO :: Sem (Fresh Unique : r) a -> Sem r a
runFreshUnsafePerformIO = (forall x.
Union (Fresh Unique : r) (Sem (Fresh Unique : r)) x -> Sem r x)
-> Sem (Fresh Unique : r) a -> Sem r a
forall (m :: * -> *) (r :: EffectRow) a.
Monad m =>
(forall x. Union r (Sem r) x -> m x) -> Sem r a -> m a
usingSem ((forall x.
Union (Fresh Unique : r) (Sem (Fresh Unique : r)) x -> Sem r x)
-> Sem (Fresh Unique : r) a -> Sem r a)
-> (forall x.
Union (Fresh Unique : r) (Sem (Fresh Unique : r)) x -> Sem r x)
-> Sem (Fresh Unique : r) a
-> Sem r a
forall a b. (a -> b) -> a -> b
$ \Union (Fresh Unique : r) (Sem (Fresh Unique : r)) x
u ->
case Union (Fresh Unique : r) (Sem (Fresh Unique : r)) x
-> Either
(Union r (Sem (Fresh Unique : r)) x)
(Weaving (Fresh Unique) (Sem (Fresh Unique : r)) x)
forall (e :: (* -> *) -> * -> *) (r :: EffectRow) (m :: * -> *) a.
Union (e : r) m a -> Either (Union r m a) (Weaving e m a)
decomp Union (Fresh Unique : r) (Sem (Fresh Unique : r)) x
u of
Right (Weaving Fresh Unique (Sem rInitial) a
Fresh f ()
s forall x. f (Sem rInitial x) -> Sem (Fresh Unique : r) (f x)
_ f a -> x
ex forall x. f x -> Maybe x
_) -> do
let !uniq :: Unique
uniq = IO Unique -> Unique
forall a. IO a -> a
unsafePerformIO (Union (Fresh Unique : r) (Sem (Fresh Unique : r)) x -> IO Unique
forall (r :: EffectRow) a.
Union (Fresh Unique : r) (Sem (Fresh Unique : r)) a -> IO Unique
newUnique' Union (Fresh Unique : r) (Sem (Fresh Unique : r)) x
u)
{-# NOINLINE uniq #-}
x -> Sem r x
forall (f :: * -> *) a. Applicative f => a -> f a
pure (x -> Sem r x) -> x -> Sem r x
forall a b. (a -> b) -> a -> b
$ f a -> x
ex (Unique
uniq Unique -> f () -> f Unique
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ f ()
s)
Left Union r (Sem (Fresh Unique : r)) x
g -> Union r (Sem r) x -> Sem r x
forall (r :: EffectRow) a. Union r (Sem r) a -> Sem r a
liftSem ((forall x. Sem (Fresh Unique : r) x -> Sem r x)
-> Union r (Sem (Fresh Unique : r)) x -> Union r (Sem r) x
forall (m :: * -> *) (n :: * -> *) (r :: EffectRow) a.
(forall x. m x -> n x) -> Union r m a -> Union r n a
hoist forall (r :: EffectRow) a. Sem (Fresh Unique : r) a -> Sem r a
forall x. Sem (Fresh Unique : r) x -> Sem r x
runFreshUnsafePerformIO Union r (Sem (Fresh Unique : r)) x
g)
{-# NOINLINE runFreshUnsafePerformIO #-}
newUnique' :: Union (Fresh Unique ': r) (Sem (Fresh Unique ': r)) a -> IO Unique
newUnique' :: Union (Fresh Unique : r) (Sem (Fresh Unique : r)) a -> IO Unique
newUnique' (Union ElemOf e (Fresh Unique : r)
_ Weaving e (Sem (Fresh Unique : r)) a
_) = IO Unique
newUnique
{-# NOINLINE newUnique' #-}