add GEq instnaces for IORef and STRef#34
Conversation
|
Because {-# LANGUAGE GADTs #-}
import Data.GADT.Compare
import Data.GADT.Instances
import Data.IORef
import Data.Coerce
import Data.Type.Equality
newtype Int2 = Int2 Int
wrong :: Int ~ Int2 => a
wrong = error "impossible"
main :: IO ()
main = do
ref <- newIORef (1 :: Int)
let ref' :: IORef Int2
ref' = coerce ref
case geq ref ref' of
Nothing -> putStrLn "ok"
Just r -> gcastWith r wrong
{-
*Main> main
*** Exception: impossible
CallStack (from HasCallStack):
error, called at Bad.hs:12:9 in main:Main
-} |
|
Can we wrap the type parameter in something the forces a nominal role? |
|
If you can wrap IORefs, you could wrap already coerced references. One would need nominal IORef clone (and that package could depend on |
data MakeNominal a = MkNominal {-# UNPACK #-} !a
type role MakeNominal nominal
newtype NominalORef a = MkNominalORef (IORef (MakeNominal a))If you want that in a separate library, I would instead advocate solving the problem for real, with a CPP'd superclass for #if not too old GHC
class GCoercible f where
gcoercible :: f a -> f b -> Maybe (a `Coersion` b)
default gcoercible :: GEq f => f a -> f b -> Maybe (a `Coersion` b)
gcoercible x y = (\Refl -> Coercion) <$> geq x y
#endif
class
#if not too old GHC
GCoercible f
#else
()
#endif
=> GEq f where |
|
@Ericson2314 if As I mentioned. You need nominal (opaque) There could be a variant of class GCoercible f where
gIsCoercible :: f a -> f b -> Maybe (Coercion a b)then |
|
|
#46 adds @sorki Also, you could make a library that makes If a Between those two things I think this can be closed. |
PoC, taken from
hnix.