{-# language CPP #-}
{-# language GeneralizedNewtypeDeriving #-}
{-# language TypeFamilies #-}
{-# language UndecidableInstances #-}

{-# options_ghc -Wno-orphans #-}


module Nix.Fresh where

import           Nix.Prelude
import           Control.Monad.Base   ( MonadBase(..) )
import           Control.Monad.Catch  ( MonadCatch
                                      , MonadMask
                                      , MonadThrow
                                      )
import           Control.Monad.Fix    ( MonadFix )
import           Control.Monad.Ref    ( MonadAtomicRef(..)
                                      , MonadRef(Ref)
                                      )

import           Nix.Thunk

newtype FreshIdT i m a = FreshIdT (ReaderT (Ref m i) m a)
  deriving
    ( forall a b. a -> FreshIdT i m b -> FreshIdT i m a
forall a b. (a -> b) -> FreshIdT i m a -> FreshIdT i m b
forall i (m :: * -> *) a b.
Functor m =>
a -> FreshIdT i m b -> FreshIdT i m a
forall i (m :: * -> *) a b.
Functor m =>
(a -> b) -> FreshIdT i m a -> FreshIdT i m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> FreshIdT i m b -> FreshIdT i m a
$c<$ :: forall i (m :: * -> *) a b.
Functor m =>
a -> FreshIdT i m b -> FreshIdT i m a
fmap :: forall a b. (a -> b) -> FreshIdT i m a -> FreshIdT i m b
$cfmap :: forall i (m :: * -> *) a b.
Functor m =>
(a -> b) -> FreshIdT i m a -> FreshIdT i m b
Functor
    , forall a. a -> FreshIdT i m a
forall a b. FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m a
forall a b. FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m b
forall a b.
FreshIdT i m (a -> b) -> FreshIdT i m a -> FreshIdT i m b
forall a b c.
(a -> b -> c) -> FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m c
forall {i} {m :: * -> *}. Applicative m => Functor (FreshIdT i m)
forall i (m :: * -> *) a. Applicative m => a -> FreshIdT i m a
forall i (m :: * -> *) a b.
Applicative m =>
FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m a
forall i (m :: * -> *) a b.
Applicative m =>
FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m b
forall i (m :: * -> *) a b.
Applicative m =>
FreshIdT i m (a -> b) -> FreshIdT i m a -> FreshIdT i m b
forall i (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c) -> FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: forall a b. FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m a
$c<* :: forall i (m :: * -> *) a b.
Applicative m =>
FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m a
*> :: forall a b. FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m b
$c*> :: forall i (m :: * -> *) a b.
Applicative m =>
FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m b
liftA2 :: forall a b c.
(a -> b -> c) -> FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m c
$cliftA2 :: forall i (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c) -> FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m c
<*> :: forall a b.
FreshIdT i m (a -> b) -> FreshIdT i m a -> FreshIdT i m b
$c<*> :: forall i (m :: * -> *) a b.
Applicative m =>
FreshIdT i m (a -> b) -> FreshIdT i m a -> FreshIdT i m b
pure :: forall a. a -> FreshIdT i m a
$cpure :: forall i (m :: * -> *) a. Applicative m => a -> FreshIdT i m a
Applicative
    , forall a. FreshIdT i m a
forall a. FreshIdT i m a -> FreshIdT i m [a]
forall a. FreshIdT i m a -> FreshIdT i m a -> FreshIdT i m a
forall {i} {m :: * -> *}.
Alternative m =>
Applicative (FreshIdT i m)
forall i (m :: * -> *) a. Alternative m => FreshIdT i m a
forall i (m :: * -> *) a.
Alternative m =>
FreshIdT i m a -> FreshIdT i m [a]
forall i (m :: * -> *) a.
Alternative m =>
FreshIdT i m a -> FreshIdT i m a -> FreshIdT i m a
forall (f :: * -> *).
Applicative f
-> (forall a. f a)
-> (forall a. f a -> f a -> f a)
-> (forall a. f a -> f [a])
-> (forall a. f a -> f [a])
-> Alternative f
many :: forall a. FreshIdT i m a -> FreshIdT i m [a]
$cmany :: forall i (m :: * -> *) a.
Alternative m =>
FreshIdT i m a -> FreshIdT i m [a]
some :: forall a. FreshIdT i m a -> FreshIdT i m [a]
$csome :: forall i (m :: * -> *) a.
Alternative m =>
FreshIdT i m a -> FreshIdT i m [a]
<|> :: forall a. FreshIdT i m a -> FreshIdT i m a -> FreshIdT i m a
$c<|> :: forall i (m :: * -> *) a.
Alternative m =>
FreshIdT i m a -> FreshIdT i m a -> FreshIdT i m a
empty :: forall a. FreshIdT i m a
$cempty :: forall i (m :: * -> *) a. Alternative m => FreshIdT i m a
Alternative
    , forall a. a -> FreshIdT i m a
forall a b. FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m b
forall a b.
FreshIdT i m a -> (a -> FreshIdT i m b) -> FreshIdT i m b
forall {i} {m :: * -> *}. Monad m => Applicative (FreshIdT i m)
forall i (m :: * -> *) a. Monad m => a -> FreshIdT i m a
forall i (m :: * -> *) a b.
Monad m =>
FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m b
forall i (m :: * -> *) a b.
Monad m =>
FreshIdT i m a -> (a -> FreshIdT i m b) -> FreshIdT i m b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: forall a. a -> FreshIdT i m a
$creturn :: forall i (m :: * -> *) a. Monad m => a -> FreshIdT i m a
>> :: forall a b. FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m b
$c>> :: forall i (m :: * -> *) a b.
Monad m =>
FreshIdT i m a -> FreshIdT i m b -> FreshIdT i m b
>>= :: forall a b.
FreshIdT i m a -> (a -> FreshIdT i m b) -> FreshIdT i m b
$c>>= :: forall i (m :: * -> *) a b.
Monad m =>
FreshIdT i m a -> (a -> FreshIdT i m b) -> FreshIdT i m b
Monad
    , forall a. String -> FreshIdT i m a
forall {i} {m :: * -> *}. MonadFail m => Monad (FreshIdT i m)
forall i (m :: * -> *) a. MonadFail m => String -> FreshIdT i m a
forall (m :: * -> *).
Monad m -> (forall a. String -> m a) -> MonadFail m
fail :: forall a. String -> FreshIdT i m a
$cfail :: forall i (m :: * -> *) a. MonadFail m => String -> FreshIdT i m a
MonadFail
    , forall a. FreshIdT i m a
forall a. FreshIdT i m a -> FreshIdT i m a -> FreshIdT i m a
forall {i} {m :: * -> *}. MonadPlus m => Monad (FreshIdT i m)
forall {i} {m :: * -> *}. MonadPlus m => Alternative (FreshIdT i m)
forall i (m :: * -> *) a. MonadPlus m => FreshIdT i m a
forall i (m :: * -> *) a.
MonadPlus m =>
FreshIdT i m a -> FreshIdT i m a -> FreshIdT i m a
forall (m :: * -> *).
Alternative m
-> Monad m
-> (forall a. m a)
-> (forall a. m a -> m a -> m a)
-> MonadPlus m
mplus :: forall a. FreshIdT i m a -> FreshIdT i m a -> FreshIdT i m a
$cmplus :: forall i (m :: * -> *) a.
MonadPlus m =>
FreshIdT i m a -> FreshIdT i m a -> FreshIdT i m a
mzero :: forall a. FreshIdT i m a
$cmzero :: forall i (m :: * -> *) a. MonadPlus m => FreshIdT i m a
MonadPlus
    , forall a. (a -> FreshIdT i m a) -> FreshIdT i m a
forall {i} {m :: * -> *}. MonadFix m => Monad (FreshIdT i m)
forall i (m :: * -> *) a.
MonadFix m =>
(a -> FreshIdT i m a) -> FreshIdT i m a
forall (m :: * -> *).
Monad m -> (forall a. (a -> m a) -> m a) -> MonadFix m
mfix :: forall a. (a -> FreshIdT i m a) -> FreshIdT i m a
$cmfix :: forall i (m :: * -> *) a.
MonadFix m =>
(a -> FreshIdT i m a) -> FreshIdT i m a
MonadFix
    , forall a. a -> FreshIdT i m (Ref (FreshIdT i m) a)
forall a. Ref (FreshIdT i m) a -> FreshIdT i m a
forall a. Ref (FreshIdT i m) a -> a -> FreshIdT i m ()
forall a. Ref (FreshIdT i m) a -> (a -> a) -> FreshIdT i m ()
forall {i} {m :: * -> *}. MonadRef m => Monad (FreshIdT i m)
forall i (m :: * -> *) a.
MonadRef m =>
a -> FreshIdT i m (Ref (FreshIdT i m) a)
forall i (m :: * -> *) a.
MonadRef m =>
Ref (FreshIdT i m) a -> FreshIdT i m a
forall i (m :: * -> *) a.
MonadRef m =>
Ref (FreshIdT i m) a -> a -> FreshIdT i m ()
forall i (m :: * -> *) a.
MonadRef m =>
Ref (FreshIdT i m) a -> (a -> a) -> FreshIdT i m ()
forall (m :: * -> *).
Monad m
-> (forall a. a -> m (Ref m a))
-> (forall a. Ref m a -> m a)
-> (forall a. Ref m a -> a -> m ())
-> (forall a. Ref m a -> (a -> a) -> m ())
-> (forall a. Ref m a -> (a -> a) -> m ())
-> MonadRef m
modifyRef' :: forall a. Ref (FreshIdT i m) a -> (a -> a) -> FreshIdT i m ()
$cmodifyRef' :: forall i (m :: * -> *) a.
MonadRef m =>
Ref (FreshIdT i m) a -> (a -> a) -> FreshIdT i m ()
modifyRef :: forall a. Ref (FreshIdT i m) a -> (a -> a) -> FreshIdT i m ()
$cmodifyRef :: forall i (m :: * -> *) a.
MonadRef m =>
Ref (FreshIdT i m) a -> (a -> a) -> FreshIdT i m ()
writeRef :: forall a. Ref (FreshIdT i m) a -> a -> FreshIdT i m ()
$cwriteRef :: forall i (m :: * -> *) a.
MonadRef m =>
Ref (FreshIdT i m) a -> a -> FreshIdT i m ()
readRef :: forall a. Ref (FreshIdT i m) a -> FreshIdT i m a
$creadRef :: forall i (m :: * -> *) a.
MonadRef m =>
Ref (FreshIdT i m) a -> FreshIdT i m a
newRef :: forall a. a -> FreshIdT i m (Ref (FreshIdT i m) a)
$cnewRef :: forall i (m :: * -> *) a.
MonadRef m =>
a -> FreshIdT i m (Ref (FreshIdT i m) a)
MonadRef
    , forall a b. Ref (FreshIdT i m) a -> (a -> (a, b)) -> FreshIdT i m b
forall {i} {m :: * -> *}.
MonadAtomicRef m =>
MonadRef (FreshIdT i m)
forall i (m :: * -> *) a b.
MonadAtomicRef m =>
Ref (FreshIdT i m) a -> (a -> (a, b)) -> FreshIdT i m b
forall (m :: * -> *).
MonadRef m
-> (forall a b. Ref m a -> (a -> (a, b)) -> m b)
-> (forall a b. Ref m a -> (a -> (a, b)) -> m b)
-> MonadAtomicRef m
atomicModifyRef' :: forall a b. Ref (FreshIdT i m) a -> (a -> (a, b)) -> FreshIdT i m b
$catomicModifyRef' :: forall i (m :: * -> *) a b.
MonadAtomicRef m =>
Ref (FreshIdT i m) a -> (a -> (a, b)) -> FreshIdT i m b
atomicModifyRef :: forall a b. Ref (FreshIdT i m) a -> (a -> (a, b)) -> FreshIdT i m b
$catomicModifyRef :: forall i (m :: * -> *) a b.
MonadAtomicRef m =>
Ref (FreshIdT i m) a -> (a -> (a, b)) -> FreshIdT i m b
MonadAtomicRef
    , forall a. IO a -> FreshIdT i m a
forall {i} {m :: * -> *}. MonadIO m => Monad (FreshIdT i m)
forall i (m :: * -> *) a. MonadIO m => IO a -> FreshIdT i m a
forall (m :: * -> *).
Monad m -> (forall a. IO a -> m a) -> MonadIO m
liftIO :: forall a. IO a -> FreshIdT i m a
$cliftIO :: forall i (m :: * -> *) a. MonadIO m => IO a -> FreshIdT i m a
MonadIO
    , forall e a.
Exception e =>
FreshIdT i m a -> (e -> FreshIdT i m a) -> FreshIdT i m a
forall {i} {m :: * -> *}. MonadCatch m => MonadThrow (FreshIdT i m)
forall i (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
FreshIdT i m a -> (e -> FreshIdT i m a) -> FreshIdT i m a
forall (m :: * -> *).
MonadThrow m
-> (forall e a. Exception e => m a -> (e -> m a) -> m a)
-> MonadCatch m
catch :: forall e a.
Exception e =>
FreshIdT i m a -> (e -> FreshIdT i m a) -> FreshIdT i m a
$ccatch :: forall i (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
FreshIdT i m a -> (e -> FreshIdT i m a) -> FreshIdT i m a
MonadCatch
    , forall e a. Exception e => e -> FreshIdT i m a
forall {i} {m :: * -> *}. MonadThrow m => Monad (FreshIdT i m)
forall i (m :: * -> *) e a.
(MonadThrow m, Exception e) =>
e -> FreshIdT i m a
forall (m :: * -> *).
Monad m -> (forall e a. Exception e => e -> m a) -> MonadThrow m
throwM :: forall e a. Exception e => e -> FreshIdT i m a
$cthrowM :: forall i (m :: * -> *) e a.
(MonadThrow m, Exception e) =>
e -> FreshIdT i m a
MonadThrow
    , forall b.
((forall a. FreshIdT i m a -> FreshIdT i m a) -> FreshIdT i m b)
-> FreshIdT i m b
forall a b c.
FreshIdT i m a
-> (a -> ExitCase b -> FreshIdT i m c)
-> (a -> FreshIdT i m b)
-> FreshIdT i m (b, c)
forall {i} {m :: * -> *}. MonadMask m => MonadCatch (FreshIdT i m)
forall i (m :: * -> *) b.
MonadMask m =>
((forall a. FreshIdT i m a -> FreshIdT i m a) -> FreshIdT i m b)
-> FreshIdT i m b
forall i (m :: * -> *) a b c.
MonadMask m =>
FreshIdT i m a
-> (a -> ExitCase b -> FreshIdT i m c)
-> (a -> FreshIdT i m b)
-> FreshIdT i m (b, c)
forall (m :: * -> *).
MonadCatch m
-> (forall b. ((forall a. m a -> m a) -> m b) -> m b)
-> (forall b. ((forall a. m a -> m a) -> m b) -> m b)
-> (forall a b c.
    m a -> (a -> ExitCase b -> m c) -> (a -> m b) -> m (b, c))
-> MonadMask m
generalBracket :: forall a b c.
FreshIdT i m a
-> (a -> ExitCase b -> FreshIdT i m c)
-> (a -> FreshIdT i m b)
-> FreshIdT i m (b, c)
$cgeneralBracket :: forall i (m :: * -> *) a b c.
MonadMask m =>
FreshIdT i m a
-> (a -> ExitCase b -> FreshIdT i m c)
-> (a -> FreshIdT i m b)
-> FreshIdT i m (b, c)
uninterruptibleMask :: forall b.
((forall a. FreshIdT i m a -> FreshIdT i m a) -> FreshIdT i m b)
-> FreshIdT i m b
$cuninterruptibleMask :: forall i (m :: * -> *) b.
MonadMask m =>
((forall a. FreshIdT i m a -> FreshIdT i m a) -> FreshIdT i m b)
-> FreshIdT i m b
mask :: forall b.
((forall a. FreshIdT i m a -> FreshIdT i m a) -> FreshIdT i m b)
-> FreshIdT i m b
$cmask :: forall i (m :: * -> *) b.
MonadMask m =>
((forall a. FreshIdT i m a -> FreshIdT i m a) -> FreshIdT i m b)
-> FreshIdT i m b
MonadMask
    )

instance MonadTrans (FreshIdT i) where
  lift :: forall (m :: * -> *) a. Monad m => m a -> FreshIdT i m a
lift = forall i (m :: * -> *) a. ReaderT (Ref m i) m a -> FreshIdT i m a
FreshIdT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift

instance MonadBase b m => MonadBase b (FreshIdT i m) where
  liftBase :: forall α. b α -> FreshIdT i m α
liftBase = forall i (m :: * -> *) a. ReaderT (Ref m i) m a -> FreshIdT i m a
FreshIdT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
liftBase

instance
  ( MonadAtomicRef m
  , Eq i
  , Ord i
  , Show i
  , Enum i
  , Typeable i
  )
  => MonadThunkId (FreshIdT i m)
 where
  type ThunkId (FreshIdT i m) = i
  freshId :: FreshIdT i m (ThunkId (FreshIdT i m))
freshId = forall i (m :: * -> *) a. ReaderT (Ref m i) m a -> FreshIdT i m a
FreshIdT forall a b. (a -> b) -> a -> b
$ do
    Ref m i
v <- forall r (m :: * -> *). MonadReader r m => m r
ask
    forall (m :: * -> *) a b.
MonadAtomicRef m =>
Ref m a -> (a -> (a, b)) -> m b
atomicModifyRef Ref m i
v (\i
i -> (forall a. Enum a => a -> a
succ i
i, i
i))

runFreshIdT :: Functor m => FreshIdT i m a -> Ref m i -> m a
runFreshIdT :: forall (m :: * -> *) i a.
Functor m =>
FreshIdT i m a -> Ref m i -> m a
runFreshIdT = forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT forall b c a. (b -> c) -> (a -> b) -> a -> c
. coerce :: forall a b. Coercible a b => a -> b
coerce