Eu tenho um tipo Id a
e estou tentando evitar a coação acidental, por exemplo, um Id Double
para um Id Int
.
Se eu entendo as funções de digitação corretamente, o seguinte não deve ser compilado.
{-# 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)
Infelizmente, ele faz:
Prelude> :load Id.hs
[1 of 1] Compiling Main ( Id.hs, interpreted )
Ok, one module loaded.
*Main> :type badKey
badKey :: Id Int
O que estou perdendo nas funções de tipo?
type role
era fazer com que não fosse esse o caso. Esta pergunta está perguntando por que isso não funcionou.
a
inId
é uma variável fantasma e não tem impacto no valor real interno. Se você tivessenewtype Id a = Id a
, a coerção teria falhado.