Ho un tipo Id a
e sto cercando di prevenire la coercizione accidentale, ad esempio, da an Id Double
a an Id Int
.
Se capisco correttamente i ruoli di tipo, non dovrebbe essere compilato quanto segue.
{-# 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)
Sfortunatamente, fa:
Prelude> :load Id.hs
[1 of 1] Compiling Main ( Id.hs, interpreted )
Ok, one module loaded.
*Main> :type badKey
badKey :: Id Int
Cosa mi manca dei ruoli di tipo?
type role
stato quello di non farlo. Questa domanda è: perché non ha funzionato.
a
inId
è una variabile fantasma e non ha alcun impatto sul valore reale all'interno. Se lo avessi fattonewtype Id a = Id a
, la coercizione sarebbe fallita.