Geben Sie Rollen und verwirrendes Verhalten durch "Zwang" ein

11

Ich habe eine Art Id aund ich versuche , aus Versehen Nötigung zu verhindern, beispielsweise ein Id Doublezu ein Id Int.

Wenn ich Typrollen richtig verstehe, sollte Folgendes nicht kompiliert werden.

{-# 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)

Leider tut es:

Prelude> :load Id.hs
[1 of 1] Compiling Main             ( Id.hs, interpreted )
Ok, one module loaded.
*Main> :type badKey
badKey :: Id Int

Was fehlt mir an Typrollen?

Gebratene Brice
quelle
ain Idist eine Phantomvariable und hat keinen Einfluss auf den tatsächlichen Wert im Inneren. Wenn Sie es newtype Id a = Id agetan hätten, wäre der Zwang gescheitert.
Lehins
@lehins Es type roleging darum, dass dies nicht der Fall ist. Diese Frage fragt, warum das nicht funktioniert hat.
Joseph Sible-Reinstate Monica

Antworten:

12

Coerciblehat drei mögliche "Arten" von Instanzen (die vom Compiler automatisch generiert und nicht vom Benutzer definiert werden). Nur einer von ihnen ist tatsächlich von Rollen betroffen .

  • Jeder Typ ist für sich selbst erzwungen.
  • Sie können "unter" einen Typkonstruktor zwingen, vorausgesetzt, die betroffenen Typvariablen sind representationaloder phantom. Zum Beispiel können Sie ein Map Char Intin ein Map Char (Data.Monoid.Sum Int)weil zwingen, weil Mapwir haben type role Map nominal representational.
  • Sie können jederzeit einen Newtype zum zugrunde liegenden Typ erzwingen und umgekehrt, vorausgesetzt, der Newtype-Konstruktor befindet sich im Gültigkeitsbereich. Dies ignoriert alle Rollen! Das Grundprinzip ist, dass Sie, da der Konstruktor verfügbar ist, jederzeit manuell ein- und auspacken können, sodass die Rolle Ihnen ohnehin keine Sicherheit bietet.

In Ihrem Beispiel gilt die dritte Regel. Wäre der neue Typ in einem anderen Modul definiert und der Konstruktor nicht importiert worden, wäre der Zwang fehlgeschlagen (damit er wieder funktioniert, müssten Sie die Rolle auf wechseln phantom).

Das etwas überraschende spezielle Verhalten für Newtypes wird in dieser GHC-Ausgabe erläutert .

danidiaz
quelle