{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}

{-# OPTIONS_GHC -Wno-orphans #-}


module Nix.Var where

import           Control.Monad.Ref
import           Data.GADT.Compare  ( GEq(..) )
import           Data.STRef         ( STRef )
import           Type.Reflection    ( (:~:)(Refl) )

import           Unsafe.Coerce      ( unsafeCoerce )

type Var m = Ref m

type MonadVar m = MonadAtomicRef m

eqVar :: forall m a . GEq (Ref m) => Ref m a -> Ref m a -> Bool
eqVar :: Ref m a -> Ref m a -> Bool
eqVar Ref m a
a Ref m a
b = Maybe (a :~: a) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe (a :~: a) -> Bool) -> Maybe (a :~: a) -> Bool
forall a b. (a -> b) -> a -> b
$ Ref m a -> Ref m a -> Maybe (a :~: a)
forall k (f :: k -> *) (a :: k) (b :: k).
GEq f =>
f a -> f b -> Maybe (a :~: b)
geq Ref m a
a Ref m a
b

newVar :: MonadRef m => a -> m (Ref m a)
newVar :: a -> m (Ref m a)
newVar = a -> m (Ref m a)
forall (m :: * -> *) a. MonadRef m => a -> m (Ref m a)
newRef

readVar :: MonadRef m => Ref m a -> m a
readVar :: Ref m a -> m a
readVar = Ref m a -> m a
forall (m :: * -> *) a. MonadRef m => Ref m a -> m a
readRef

writeVar :: MonadRef m => Ref m a -> a -> m ()
writeVar :: Ref m a -> a -> m ()
writeVar = Ref m a -> a -> m ()
forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> m ()
writeRef

atomicModifyVar :: MonadAtomicRef m => Ref m a -> (a -> (a, b)) -> m b
atomicModifyVar :: Ref m a -> (a -> (a, b)) -> m b
atomicModifyVar = Ref m a -> (a -> (a, b)) -> m b
forall (m :: * -> *) a b.
MonadAtomicRef m =>
Ref m a -> (a -> (a, b)) -> m b
atomicModifyRef

--TODO: Upstream GEq instances
--  2021-02-25: NOTE: Currently, upstreaming would require adding a dependency on the according packages.
instance GEq IORef where
  IORef a
a geq :: IORef a -> IORef b -> Maybe (a :~: b)
`geq` IORef b
b =
    Maybe (a :~: b) -> Maybe (a :~: b) -> Bool -> Maybe (a :~: b)
forall a. a -> a -> Bool -> a
bool
      Maybe (a :~: b)
forall a. Maybe a
Nothing
      ((a :~: b) -> Maybe (a :~: b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((a :~: b) -> Maybe (a :~: b)) -> (a :~: b) -> Maybe (a :~: b)
forall a b. (a -> b) -> a -> b
$ (Any :~: Any) -> a :~: b
forall a b. a -> b
unsafeCoerce Any :~: Any
forall k (a :: k). a :~: a
Refl)
      (IORef a
a IORef a -> IORef a -> Bool
forall a. Eq a => a -> a -> Bool
== IORef b -> IORef a
forall a b. a -> b
unsafeCoerce IORef b
b)

instance GEq (STRef s) where
  STRef s a
a geq :: STRef s a -> STRef s b -> Maybe (a :~: b)
`geq` STRef s b
b =
    Maybe (a :~: b) -> Maybe (a :~: b) -> Bool -> Maybe (a :~: b)
forall a. a -> a -> Bool -> a
bool
      Maybe (a :~: b)
forall a. Maybe a
Nothing
      ((a :~: b) -> Maybe (a :~: b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((a :~: b) -> Maybe (a :~: b)) -> (a :~: b) -> Maybe (a :~: b)
forall a b. (a -> b) -> a -> b
$ (Any :~: Any) -> a :~: b
forall a b. a -> b
unsafeCoerce Any :~: Any
forall k (a :: k). a :~: a
Refl)
      (STRef s a
a STRef s a -> STRef s a -> Bool
forall a. Eq a => a -> a -> Bool
== STRef s b -> STRef s a
forall a b. a -> b
unsafeCoerce STRef s b
b)