2016-12-23 2 views
1

Ich mag es nicht, Summen typisierte Werte mit Musterabgleich zu destrukturieren. Es fühlt sich für mich wegen seines spitzen Stils fremdartig an. Ich schreibe lieber und verwende switch Funktionen für Summenarten.Punktfreie Destrukturierung mit GHC

Meine Frage ist jede Summe Typ im Allgemeinen, aber ich zeige es auf Either als Beispiel:

data Processor cl cr r = MakeProcessor { l :: cl -> r, r :: cr -> r } 

switch :: Processor cl cr r -> Either cl cr -> r 
switch p ei = 
    case ei of 
     Left x -> l p x 
     Right x -> r p x 

Mit dieser Erweiterung zu Either:

statt dem:

map f e = 
    case e of 
     Left x -> Left x 
     Right x -> Right (f x) 

Ich kann dies schreiben:

map f = switch (MakeProcessor { l : Left, r : f >>> Right }) 

, die ich für die meisten Situationen besser fühle.

Um solche Erweiterung Zeug schreiben [Processor, switch] für eine Summenart ist mechanische Arbeit. Also frage ich mich: Gibt es eine Möglichkeit, den Compiler [GHC] dazu zu bringen, es für mich zu tun? Oder eine andere Möglichkeit, die Summe typisierter Werte im sinnlosen Stil zu destrukturieren?


Hinweis: benutzte ich Either als nur ein Beispiel. Either war eine falsche Wahl, da viele Leser dachten, dass meine Frage speziell Either war, und wies mich daher auf either. Ich sollte eine Summe Typ, der nicht in der Basisbibliothek, wie

data Result a b = Fail a | Success b 
+0

Sie könnten die "Objektiv" -Bibliothek hilfreich finden. Es würde Ihnen erlauben, Ihre 'map'-Funktion als' over_Right' zu schreiben. –

+0

Ich denke, dass _Right von TemplateHaskell stammt, oder? Vielleicht ist das zu streng, aber ich habe TH gemieden, weil es nicht mit SafeHaskell kompatibel ist. – libeako

+0

Mein 'Entweder'-Beispiel ist nur ein Beispiel meiner Methode, um Mustervergleiche zu vermeiden. Es ist eine sicherere Version der 'entweder' Funktion in der Basisbibliothek. Meine Frage geht nicht speziell auf "Entweder", ich benutze es nur als Beispiel. – libeako

Antwort

2

Die kurze Antwort ist nein (besonders ohne Vorlage Haskell).

Wie viele Konstrukte in der funktionalen Programmierung können Sie es jedoch auf den Kopf stellen. Verwenden Sie eine Church/Scott-Codierung (sie sind identisch, wenn der Datentyp nicht rekursiv ist).

newtype ChurchEither a b = ChurchEither { switch :: forall c. (a -> c) -> (b -> c) -> c } 

, in dem erhalten Sie die Ausscheidungs ​​switch kostenlos, weil es die Definition der Art ist, aber Sie müssen die Konstrukteure selbst schreiben

left x = ChurchEither (\l r -> l x) 
right x = ChurchEither (\l r -> r x) 

so haben Sie nicht wirklich etwas gewonnen boilerplate- weise.

+0

Ich betrachte Ihre erste Zeile als die Antwort auf meine Frage. – libeako

4

Die either Funktion können Sie festlegen, getrennte Funktionen zu Left und Right Werte in einem Either a b Wert aufzubringen:

switch p ei = either (l p) (r p) ei 

Sie können sofort ei von beiden Seiten fallen

switch p = either (l p) (r p) 

und Sie zu erhalten Verwenden Sie die Applicative Instanz kann für Funktionen p fallen:

switch = either <$> l <*> r 

Für eine beliebige Summe Typ, benötigen Sie eine entsprechende catamorphism, zu schaffen, die für eine Funktion wie either der Phantasiename ist, der einen Wert eingewickelt reduziert durch der Summentyp zum umschlossenen Typ.

+0

Mein 'Entweder'-Beispiel ist nur ein Beispiel für meine Methode zur Vermeidung von Mustererkennung. Es ist eine sicherere Version der 'entweder' Funktion in der Basisbibliothek. Meine Frage geht nicht speziell auf "Entweder", ich benutze es nur als Beispiel. – libeako

+1

Können Sie den Sinn erklären, in dem Ihre Methode sicherer ist als "entweder"? –

+0

Mehr sicher: Ein möglicher Codierungsfehler ist es, die Reihenfolge der Parameter von 'entweder' umzukehren. Wenn die Art der Werte, die in "Entweder" gespeichert sind, gleich ist, gibt es keinen Tippfehler. 'Entweder 'ist ein schlechtes Beispiel, um diese Art von Fehler Möglichkeit zu demonstrieren, aber ich denke, im Allgemeinen für andere Summen Typen ist die Gefahr real. Daher setze ich die Prozessorfunktionen eher in einen Datensatz, nur damit ich sie benennen kann. – libeako