Escriba roles y comportamientos confusos por `coerce`

11

Tengo un tipo Id ay estoy tratando de evitar la coerción accidental, por ejemplo, un Id Doublea 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?

Brice frito
fuente
ain Ides una variable fantasma y no tiene impacto en el valor real en su interior. Si lo hubiera hecho newtype Id a = Id a, entonces la coerción habría fallado.
lehins
@lehins El objetivo de esto type roleera hacer que ese no fuera el caso. Esta pregunta es por qué eso no funcionó.
Joseph Sible-Reinstate a Monica el

Respuestas:

12

Coercibletiene tres posibles "tipos" de instancias (que son generadas automáticamente por el compilador, no definidas por el usuario). Solo uno de ellos está afectado por los roles .

  • Cada tipo es coercible a sí mismo.
  • Puede forzar "debajo" de un constructor de tipos, siempre que las variables de tipo afectadas sean representationalo phantom. Por ejemplo, puede coaccionar un Map Char Inta Map Char (Data.Monoid.Sum Int)porque porque Maptenemos type role Map nominal representational.
  • Puede siempre coaccionar a un newtype al tipo subyacente y viceversa, siempre que el constructor newtype es en su alcance. ¡Esto ignora todos los roles! La razón es que, dado que el constructor está disponible, siempre puede envolver y desenvolver manualmente, por lo que el rol no le brinda ninguna seguridad de todos modos.

En su ejemplo, se aplica la tercera regla. Si el nuevo tipo se hubiera definido en otro módulo y el constructor no se hubiera importado, la coerción habría fallado (para que funcione nuevamente, necesitaría cambiar el rol a phantom).

El comportamiento especial algo sorprendente para los nuevos tipos se explica en este número de GHC.

danidiaz
fuente