{-# language AllowAmbiguousTypes #-}
{-# language ConstraintKinds #-}

{-# options_ghc -Wno-orphans #-}
{-# options_ghc -Wno-unused-top-binds #-}

module Nix.Var ()
where

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

import           Unsafe.Coerce      ( unsafeCoerce )

eqVar :: 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

--TODO: Upstream GEq instances
-- Upstream thread: https://github.com/haskellari/some/pull/34
instance GEq IORef where
  geq :: IORef a -> IORef b -> Maybe (a :~: b)
geq = IORef a -> IORef b -> Maybe (a :~: b)
forall a b c. Eq a => a -> b -> Maybe c
gEqual

instance GEq (STRef s) where
  geq :: STRef s a -> STRef s b -> Maybe (a :~: b)
geq = STRef s a -> STRef s b -> Maybe (a :~: b)
forall a b c. Eq a => a -> b -> Maybe c
gEqual

-- | Simply a helper function
gEqual :: Eq a => a -> b -> Maybe c
gEqual :: a -> b -> Maybe c
gEqual a
a b
b =
  Maybe c -> Maybe c -> Bool -> Maybe c
forall a. a -> a -> Bool -> a
bool
    Maybe c
forall a. Maybe a
Nothing
    (c -> Maybe c
forall (f :: * -> *) a. Applicative f => a -> f a
pure (c -> Maybe c) -> c -> Maybe c
forall a b. (a -> b) -> a -> b
$ (Any :~: Any) -> c
forall a b. a -> b
unsafeCoerce Any :~: Any
forall k (a :: k). a :~: a
Refl)
    (a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== b -> a
forall a b. a -> b
unsafeCoerce b
b)