Admissble type role overrides

66 Views Asked by At

In GHC Haskell, Map k v has a type role declaration for k to be nominal. This is because the user can otherwise coerce k to another type with the same representation but different Ord instance, breaking the invariants.

However, I have some newtypes whose Ord instances are inherited. In this case unsafeCoerce seems to do the job (correct me if there are subtleties I don't know), but this completely turns off the typechecking for the coercion, which keeps me awake at night. In my specific use case, I have a type MyWrapper k, and I would like to be able to declare some newtypes k1 -> k2 as admissible for safe coercion even when it is the argument of MyWrapper. Is this possible? What are some other workarounds?

2

There are 2 best solutions below

2
leftaroundabout On BEST ANSWER

I'd say it makes sense to introduce a typeclass for this specific purpose. Not to actually do the conversion, just to alias a version of unsafeCoerce restricted to the case where it actually is safe.

{-# LANGUAGE MultiParamTypeClasses #-}

class (Ord a, Ord b) => CompatibleOrd a b
  -- no methods

instance CompatibleOrd YourBaseType YourNewtype

coerceKeysMonotonically :: (Coercible a b, CompatibleOrd a b)
          => Map a y -> Map b y
coerceKeysMonotonically = unsafeCoerce
0
Iceland_jack On

I created a ticket that proposed this: "Make coerce-derived dictionaries coercible"

https://gitlab.haskell.org/ghc/ghc/-/issues/20815