I have a type Id a
and I'm trying to prevent accidentally coercing, e.g., an Id Double
to an Id Int
.
If I understand type roles correctly, the following should not compile.
{-# LANGUAGE RoleAnnotations #-}
import Data.Coerce (coerce)
type role Id nominal
newtype Id a = Id String
badKey :: Id Int
badKey = coerce (Id "I point to a Double" :: Id Double)
Unfortunately, it does:
Prelude> :load Id.hs
[1 of 1] Compiling Main ( Id.hs, interpreted )
Ok, one module loaded.
*Main> :type badKey
badKey :: Id Int
What am I missing about type roles?