Ich habe ein wirklich interessantes Beispiel in einem Scala Artikel gefunden und frage mich, wie es in Haskell kodiert sein könnte.Ein Scala Type Beispiel nach Haskell
trait Status
trait Open extends Status
trait Closed extends Status
trait Door[S <: Status]
object Door {
def apply[S <: Status] = new Door[S] {}
def open[S <: Closed](d: Door[S]) = Door[Open]
def close[S <: Open](d: Door[S]) = Door[Closed]
}
val closedDoor = Door[Closed]
val openDoor = Door.open(closedDoor)
val closedAgainDoor = Door.close(openDoor)
//val closedClosedDoor = Door.close(closedDoor) // fails to compile
//val openOpenDoor = Door.open(openDoor) // fails to compile
Diese Probe kodiert auf der Typebene, die Sie nur eine geschlossene Door
öffnen kann, und nur ein offenes Door
schließen. Mein erster Versuch wurde mit nur einfache Datentypen, aber nicht wie beabsichtigt:
data Status = Open | Closed deriving (Show)
data Door = Door Status deriving (Show)
open :: Door -> Door
open (Door Closed) = Door Open
close :: Door -> Door
close (Door Open) = Door Closed
main = do
let closedDoor = (Door Closed)
let openDoor = open closedDoor
let closedAgainDoor = close openDoor
let closeClosedDoor = close closedDoor
let openOpenedDoor = open openDoor
print closedAgainDoor
Dies kompiliert tatsächlich (es sei denn, ich versuche closeClosedDoor
oder openOpenedDoor
zu drucken, die dann beschwert sich über nicht erschöpfende Muster in Funktion offen, das ist offensichtlich)
Also ich versuche herauszufinden, ob GADTs unsere Type Families diese Aufgabe erfüllen können, aber ich bin noch nicht in der Lage zu verstehen, wie es geht.
Irgendwelche Ideen?
Sie schlagen mich auf die 'DataKinds' Antwort. Ich wollte es nicht posten, ohne es zuerst kompiliert zu haben, aber ich musste zuerst 'stack setup' ausführen, und das dauert eine Weile in einem langsamen Netzwerk, lol. Ich mag die 'toggle' Idee mit' TypeFamilies', hatte aber nicht daran gedacht. – bheklilr
Schön, ich glaube nicht, dass ich selbst dazu gekommen wäre, immer noch die fortgeschrittenen Merkmale der Sprache zu lernen. –
Für eine bessere Schlussfolgerung, 'toggle :: (s ~ Umschalt t, t ~ Toggle s) => Tür s -> Tür t'. Oder 'Klasse Toggled s t | s -> t, t -> s wo toggle :: Tür s -> Tür t'. Du könntest wahrscheinlich eine injektive Art für GHC 8 verwenden, aber ich kaufe diese noch nicht. – dfeuer