2016-04-23 6 views
0

Ich versuche, einen Datensatz zu erstellen, in dem eines der Felder hat einen Typen, der nicht exportiert wird, da es einen Smart-Konstruktor verwenden. Die Verwendung des intelligenten Konstruktors als Typ funktioniert nicht.Nehmen Syntax Feldtyp Annotation nur intelligentes Konstruktor mit

Vielleicht gibt es eine Spracherweiterung, die mir dies erlaubt, oder etwas ähnliches?

den Konstruktor exportiert zusammen mit dem Smart-Konstruktor würde mir erlauben, dieses Problem zu lösen, aber das wiederum schafft die Möglichkeit, Werte zu schaffen, die der Smart-Konstruktor nicht erlauben würde.

Die (ohne Funktion) Code, den ich jetzt haben:

import Domain (domain) -- Domain is not exported, and domain is a smart constructor for Domain 

data Rec = Rec 
    { dint :: domain Int -- what do I do here? I want it to be `Domain Int` but `Domain` isn't exported. 
    ... 
    } 
+0

Bitte geben Sie Ihren Code ein. Es ist sehr schwierig zu sagen, was hier vor sich geht. – Kwarrtz

+0

Es hört sich so an, als würden Sie Typen und Typenkonstruktoren wahrscheinlich durcheinander bringen. Ich kann jedoch nicht sagen, was Sie gepostet haben. – Kwarrtz

+0

@Kwarrtz Code hinzugefügt. –

Antwort

5

Die Frage ist hier eine Verwechslung zwischen dem Konzept eines Typkonstruktor und einem Daten Konstruktor. Der Kürze halber werde ich den Unterschied anhand eines Beispiels veranschaulichen.

data Foo a = Bar [a] 

In dem obigen Ausdruck, Foo ist der Typkonstruktor und Bar ist die Daten Konstruktor. Der Hauptunterschied besteht darin, dass Foo ein Wert in Haskell type space ist und Bar ein Wert in seinem Datenbereich ist. Ein Wert im Typraum kann nicht im Datenraum verwendet werden und umgekehrt. Zum Beispiel würde der Compiler bei den folgenden Ausdrücken einen Fehler haben.

someVariable :: Bar Int 
someVariable = Foo [15] 

Der nächste Ausdruck ist jedoch vollständig gültig.

someVariable :: Foo Int 
someVariable = Bar [15] 

Zusätzlich werden alle Typkonstruktoren muss mit einem Großbuchstaben beginnen. Alle Typen, die mit einem Kleinbuchstaben beginnen, werden als Typvariablen betrachtet, nicht als Typkonstruktoren (die a in unserer obigen Definition ist ein Beispiel dafür).

Die Einführung von Smart Konstruktoren für dieses Problem eine weitere Ebene, aber der Schlüssel ist zu verstehen, dass Smart Konstrukteure Daten Konstrukteure sind, Konstrukteure nicht geben. In Ihrer Definition von Rec versuchten Sie Ihr Mobil Konstruktor zu verwenden, domain, in der Typdeklaration für dint Feld. Da jedoch domain ein Daten Konstruktor kein Typkonstruktor ist, und es ist niedriger Fall versuchte der Haskell Compiler domain als Name eines Typs Variable zu interpretieren. Da Sie in Ihrer Definition des Typs Rec nie eine Variable mit dem Namen domain angegeben haben, hat der Compiler einen Fehler ausgelöst.

Sie nicht wirklich benötigen die Daten Konstruktor für Domain zu exportieren, das Problem zu lösen, sondern nur die Art selbst. Dies kann folgendermaßen erreicht werden.

module Domain (
    Domain(), domain, 
    ... 
    ) where 

Einschließlich Domain() in der Exportdefinition sagt Haskell den Domain Typkonstruktor, aber keine seiner Daten Konstrukteuren zu exportieren. Dies bewahrt die Sicherheit, die Sie mit dem sicheren Konstruktor haben wollten, und erlaubt es Ihnen, Typen korrekt zu definieren. Sie können Ihren neu exportierten Typ jetzt in Ihrer Definition Rec verwenden.

import Domain (Domain(), domain) 

data Rec = Rec 
    { dint :: Domain Int 
    ... 
    } 

Weitere Informationen ich Ihnen dringend empfehlen, die HaskellWiki Artikel auf constructors und smart constructors lesen.

+0

Wenn ich richtig verstanden habe, und ich sicherlich die Frage nicht gegeben habe, denke ich, dass der Typ selbst nicht exportiert wird. Wenn das der Fall ist, hat er sicherlich ein Problem und sollte den Typ oder die Datei ein Problem mit dem Bibliotheksautor exportieren. Es wäre nicht das erste Mal. –

Verwandte Themen