Digite papéis e comportamento confuso ao `coagir`

11

Eu tenho um tipo Id ae estou tentando evitar a coação acidental, por exemplo, um Id Doublepara 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?

Brice frito
fonte
ain Idé uma variável fantasma e não tem impacto no valor real interno. Se você tivesse newtype Id a = Id a, a coerção teria falhado.
Lehins 27/12/19
@lehins O objetivo da questão type roleera fazer com que não fosse esse o caso. Esta pergunta está perguntando por que isso não funcionou.
Joseph Sible-Reinstate Monica

Respostas:

12

Coerciblepossui três "tipos" possíveis de instâncias (que são gerados automaticamente pelo compilador, não definidos pelo usuário). Apenas um deles é realmente afetado pelas funções .

  • Todo tipo é coercível a si mesmo.
  • Você pode coagir "sob" um construtor de tipo, desde que as variáveis ​​de tipo afetadas sejam representationalou phantom. Por exemplo, você pode coagir um Map Char Intem um Map Char (Data.Monoid.Sum Int)porque, como Mapnós temos type role Map nominal representational.
  • Você sempre pode coagir um newtype ao tipo subjacente e vice-versa, desde que o construtor newtype esteja no escopo. Isso ignora todos os papéis! A lógica é que, dado que o construtor está disponível, você pode sempre quebrar e desembrulhar manualmente, para que a função não lhe dê nenhuma segurança.

No seu exemplo, a terceira regra se aplica. Se o newtype tivesse sido definido em outro módulo e o construtor não importado, a coerção teria falhado (para fazê-lo funcionar novamente, você precisaria mudar a função phantom).

O comportamento especial um tanto surpreendente para os novos tipos é explicado nesta edição do GHC.

danidiaz
fonte