Trebor
Trebor

Reputation: 430

Admissble type role overrides

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?

Upvotes: 4

Views: 78

Answers (2)

Iceland_jack
Iceland_jack

Reputation: 7014

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

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

Upvotes: 1

leftaroundabout
leftaroundabout

Reputation: 120751

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

Upvotes: 6

Related Questions