2016-08-07 49 views

Antwort

3

Welche Sprache verwenden Sie? Wenn es F # ist, gibt es eine Drei-Wege-Choice<'T1,'T2,'T3> type. (Auch ein 4-, 5-, 6- und 7-Wege-Choice-Typ zusätzlich zu dem "Standard" Zwei-Wege-Typ).

+0

Ich verwende TypeScript (das keine Standard-Lib außer der von JavaScript hat, denen Typen fehlen), also lasse ich mich von anderen Sprachen inspirieren –

3

Diese werden als Co-Produkte wirklich ein Either ist einfach ein 2 Argument Co-Produkt. Sie können Helfer aus der unförmigen Bibliothek verwenden, um unter Verwendung beliebiger Länge Nebenprodukten zu bauen:

type CP = Int :+: String :+: Boolean :+: CNil 

val example = Coproduct[CP]("foo") 

Sie können dann den ganzen Spaß poly Magie verwenden, um sie zuordnen oder andere Operationen ausführen:

object printer extends Poly1 { 
    implicit def caseInt = at[Int](i => i -> s"$i is an int") 
    implicit def caseString = at[String](s => s -> s"$s is a string") 
    implicit def caseBoolean = at[Boolean](b => s -> s"$b is a bool") 
} 
val mapped = example map printer 
mapped.select[(String, String)] shouldEqual "foo is a string" 

Scala. JS + Shapeless kann soweit ich weiß zusammenarbeiten, so dass Sie das geben können, was Sie wollen.

15

Ich denke, dass stark auf Typ wie folgt ist ein Anti-Muster.

Eines der schönsten Dinge, die Sie aus der Verwendung von algebraischen Datentypen erhalten, ist, dass der resultierende Typ Ihnen etwas über die Domäne sagt, mit der Sie arbeiten. Mit einem generischen Typ wie Choice<T1, T2, T3> sagen Sie wirklich nichts über die Domain.

Ich denke, option<T> (auch bekannt als Maybe) ist ziemlich klar, dass es heißt, dass ein Wert des Typs T entweder da ist oder es aus irgendeinem Grund fehlt. Ich denke, Either<'T, exn> ist immer noch ziemlich klar, dass es heißt, Sie erhalten einen Wert oder eine Ausnahme. Wenn Sie jedoch mehr als zwei Fälle haben, ist es ziemlich schwer zu verstehen, was mit den Fällen gemeint ist. Daher ist es möglicherweise eine gute Idee, einen Typ mit Namen zu definieren, der der Domäne entspricht.

(Ich verwende gelegentlich Choice<T1, T2, T3> in F #, aber die Verwendung ist in der Regel auf einen kleinen Bereich beschränkt - weniger als 50 Zeilen Code - so dass ich leicht finden kann, was die Bedeutung in der Umgebung des Codes ist, der es verbraucht .)

8

In der letzten Haskell würde ich ein bisschen Küchenspüle einschalten.

{-# LANGUAGE PolyKinds, DataKinds, GADTs, KindSignatures, 
    TypeOperators, PatternSynonyms #-} 

Dann würde ich Typ-Level-Liste Mitgliedschaft

data (:>) :: [x] -> x -> * where 
    Ze ::   (x ': xs) :> x 
    Su :: xs :> x -> (y ': xs) :> x 

definieren und jetzt habe ich alle endlichen Summen, ohne eine ganze Reihe von OneOfN Typdefinitionen zu Ankurbeln:

data Sum :: [*] -> * where 
    (:-) :: xs :> x -> x -> Sum xs 

Um Tomas 'Problem der Lesbarkeit anzugehen, verwende ich jedoch Muster-Synonyme. In der Tat ist diese Art der Sache der Grund, warum ich jahrelang über Mustersynonyme geklagt habe.

Sie können eine lustige Version von Maybe haben:

type MAYBE x = Sum '[(), x] 

pattern NOTHING :: MAYBE x 
pattern NOTHING = Ze :-() 

pattern JUST :: x -> MAYBE x 
pattern JUST x = Su Ze :- x 

und Sie selbst newtype rekursive Summen erstellen können.

newtype Tm x = Tm (Sum '[x, (Tm x, Tm x), Tm (Maybe x)]) 

pattern VAR :: x -> Tm x 
pattern VAR x = Tm (Ze :- x) 

pattern APP :: Tm x -> Tm x -> Tm x 
pattern APP f s = Tm (Su Ze :- (f, s)) 

pattern LAM :: Tm (Maybe x) -> Tm x 
pattern LAM b = Tm (Su (Su Ze) :- b) 

Die newtype Wrapper können Sie auch instance Erklärung für die Typen machen auf diese Weise gebaut.

Sie können natürlich auch Muster Synonyme verwenden, um eine iterierte Either schön ausblenden.

Diese Technik ist nicht exklusiv für Summen: Sie können es auch für Produkte tun, und das ist so ziemlich das, was in der Generics-SOP Bibliothek von de Vries und Löh passiert.

Der große Gewinn aus einer solchen Codierung ist, dass die Beschreibung der Daten selbst (Typ-Level) Daten, so dass Sie viele deriving-Stil-Funktionalität kochen, ohne den Compiler zu hacken.

In Zukunft (wenn ich meine Art und Weise haben), werden alle Datentypen sein definiert, nicht erklärt, mit Datentyp Beschreibungen von Daten aus sowohl die algebraische Struktur Einzelheiten enthält der Daten (unter Berücksichtigung generische Geräte berechnet werden) und sein Aussehen (damit Sie sehen können, was Sie tun, wenn Sie mit einem bestimmten Typ arbeiten).

Aber die Zukunft ist schon irgendwie hier.