2017-05-23 2 views
1

Wie codiert man den folgenden Summen-Typ mit Hasql? Ich habe versucht, einen Encoder sumValue :: Value SumValue zu erstellen, aber ich kann nicht Muster übereinstimmen. Z.B. Ich möchte SumBool mit Hasql.Encoders.bool und SumChar mit Hasql.Encoders.char kodieren.Hasql: kodieren Sie einen Summentyp

data SumValue 
    = SumBool !(Maybe Bool) 
    | SumChar !(Maybe Char) 
    | SumDate !(Maybe Day) 
    | ... 
    | SumUuid !(Maybe UUID) 
    deriving (Eq, Show) 
+0

Warum würden Sie überhaupt das brauchen? Es scheint, als ob Sie ein Designproblem haben. Selbst wenn Sie einen solchen Wert codieren, werden Sie wahrscheinlich auf der Serverseite in Schwierigkeiten geraten, da der Server immer einen bestimmten Typ erwartet. Können Sie Ihren Anwendungsfall näher erläutern? –

+0

Ich erstelle eine Anwendung, die CSV-Daten aus einer Datei in eine Datenbanktabelle laden kann. Der Benutzer weist Datenbankspalten CSV-Felder zu und gibt die zu verwendende Datenkonvertierung an. Da der Benutzer die Datenkonvertierung spezifiziert, weiß ich nicht im Voraus, welche Art von Daten jeder Wert sein wird, daher der Summentyp mit einem Eintrag pro Datentyp. –

+1

Immer wenn Sie eine datenbankgestützte Anwendung entwickeln, sollte die Datenbank an erster Stelle stehen. Wenn Sie Ihr Design auf diese Weise angegangen wären, hätten Sie entdeckt, dass es unmöglich gewesen wäre, ein Schema zu erstellen, das unterstützt, worauf Sie abzielen (d. H. Eine Spalte, die einen beliebigen Typ enthalten kann). Die einzige Möglichkeit zum Codieren eines Summentyps in einer relationalen Datenbank besteht darin, mehrere Spalten zu verwenden, eine für jeden Typ. Ie .: sum_bool, sum_char ... Und dann würden Sie den Summenwertgeber nicht benötigen, wie ich erwartet hatte. –

Antwort

1

Während dies sehr wahrscheinlich scheint ein Fehler in Ihrem Design, in der aktuellen Version von Hasql sein (0,19. *) Ist es möglich, einen derartigen Codierer zumindest auf der Ebene der Params zu implementieren. Allerdings muss ich feststellen, dass , sofern nicht mit einem Anwendungsfall, , die es als nützlich erweist, die Unterstützung für diese wird vollständig in der nächsten Hauptversion im Sinne der Typ-Level-Sicherheit entfernt werden.

So oder so, hier ist, wie Sie tun können, dass jetzt:

import qualified Hasql.Encoders as A 

data SumValue 
    = SumBool !(Maybe Bool) 
    | SumChar !(Maybe Char) 
    | SumDate !(Maybe Day) 
    | SumUuid !(Maybe UUID) 
    deriving (Eq, Show) 

sumValue :: A.Params SumValue 
sumValue = 
    contramap match $ 
    chosen (A.nullableValue A.bool) $ 
    chosen (A.nullableValue A.char) $ 
    chosen (A.nullableValue A.date) $ 
    A.nullableValue A.uuid 
    where 
    match = 
     \case 
     SumBool x -> Left x 
     SumChar x -> Right (Left x) 
     SumDate x -> Right (Right (Left x)) 
     SumUuid x -> Right (Right (Right x))