{-# LANGUAGE DeriveFunctor, DeriveGeneric #-}

{- | This effect provides source to an infinite source of 'Int' values, suitable for generating "fresh" values to uniquely identify data without needing to invoke random numbers or impure IO.

Predefined carriers:

* "Control.Carrier.Fresh.Strict".

-}
module Control.Effect.Fresh
( -- * Fresh effect
  Fresh(..)
, fresh
  -- * Re-exports
, Algebra
, Effect
, Has
, run
) where

import Control.Algebra
import GHC.Generics (Generic1)

-- | @since 0.1.0.0
data Fresh m k
  = Fresh (Int -> m k)
  deriving (a -> Fresh m b -> Fresh m a
(a -> b) -> Fresh m a -> Fresh m b
(forall a b. (a -> b) -> Fresh m a -> Fresh m b)
-> (forall a b. a -> Fresh m b -> Fresh m a) -> Functor (Fresh m)
forall a b. a -> Fresh m b -> Fresh m a
forall a b. (a -> b) -> Fresh m a -> Fresh m b
forall (m :: * -> *) a b. Functor m => a -> Fresh m b -> Fresh m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> Fresh m a -> Fresh m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Fresh m b -> Fresh m a
$c<$ :: forall (m :: * -> *) a b. Functor m => a -> Fresh m b -> Fresh m a
fmap :: (a -> b) -> Fresh m a -> Fresh m b
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> Fresh m a -> Fresh m b
Functor, (forall a. Fresh m a -> Rep1 (Fresh m) a)
-> (forall a. Rep1 (Fresh m) a -> Fresh m a) -> Generic1 (Fresh m)
forall a. Rep1 (Fresh m) a -> Fresh m a
forall a. Fresh m a -> Rep1 (Fresh m) a
forall k (f :: k -> *).
(forall (a :: k). f a -> Rep1 f a)
-> (forall (a :: k). Rep1 f a -> f a) -> Generic1 f
forall (m :: * -> *) a. Rep1 (Fresh m) a -> Fresh m a
forall (m :: * -> *) a. Fresh m a -> Rep1 (Fresh m) a
$cto1 :: forall (m :: * -> *) a. Rep1 (Fresh m) a -> Fresh m a
$cfrom1 :: forall (m :: * -> *) a. Fresh m a -> Rep1 (Fresh m) a
Generic1)

instance HFunctor Fresh
instance Effect   Fresh


-- | Produce a fresh (i.e. unique) 'Int'.
--
-- @
-- m '>>' 'fresh' ≠ m '>>' 'fresh' '>>' 'fresh'
-- @
--
-- @since 0.1.0.0
fresh :: Has Fresh sig m => m Int
fresh :: m Int
fresh = Fresh m Int -> m Int
forall (eff :: (* -> *) -> * -> *) (sig :: (* -> *) -> * -> *)
       (m :: * -> *) a.
(Member eff sig, Algebra sig m) =>
eff m a -> m a
send ((Int -> m Int) -> Fresh m Int
forall (m :: * -> *) k. (Int -> m k) -> Fresh m k
Fresh Int -> m Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure)