Tengo un tipo Id a
y estoy tratando de evitar la coerción accidental, por ejemplo, un Id Double
a un Id Int
.
Si entiendo los tipos de letra correctamente, no se debe compilar lo siguiente.
{-# 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)
Lamentablemente, sí:
Prelude> :load Id.hs
[1 of 1] Compiling Main ( Id.hs, interpreted )
Ok, one module loaded.
*Main> :type badKey
badKey :: Id Int
¿Qué me estoy perdiendo sobre los roles de tipo?
type role
era hacer que ese no fuera el caso. Esta pregunta es por qué eso no funcionó.
a
inId
es una variable fantasma y no tiene impacto en el valor real en su interior. Si lo hubiera hechonewtype Id a = Id a
, entonces la coerción habría fallado.