2017-07-17 3 views
0

Ich versuche zu simulieren version numbering in more generic terms in Haskell. Ich suche nach einer Haskell-Datenstruktur, die die Struktur darstellen würde, die ich selbst definiert habe (VersionNumberWithMaybe).Haskell Datenstruktur zu simulieren Alternative Version Nummerierung Ansatz

data VersionCompoundWithMaybe = Maybe Int -- Just n: 0, 1, 2, 3 ... 
              -- Nothing: x 
maybeToString :: Maybe Int -> String 
maybeToString (Just n) = (show n) 
maybeToString Nothing = "x" 

data VersionNumberWithMaybe = VC (Maybe Int)    -- VersionCompound: x, 0, 1, 2, 3 ... 
       | VNL (Maybe Int) VersionNumberWithMaybe -- VersionNumberLeft: x.x, x.0, x.1, x.2, ... , 1.0, 1.1, 1.2, ... 1.x.x, 2.x.x, 3.x.x, ... 
       | VNR VersionNumberWithMaybe (Maybe Int) -- VersionNumberRight: the same as above, only underlying structure is different for simple parsing pursposes: x.x, x.0, x.1, x.2, ... , 1.0, 1.1, 1.2, ... 1.x.x, 2.x.x, 3.x.x, ... 
       deriving (Show) 

versionNumberWithMaybeToString :: VersionNumberWithMaybe -> String 
versionNumberWithMaybeToString (VNL vc vn) = (maybeToString vc) ++ "." ++ (versionNumberWithMaybeToString vn) 
versionNumberWithMaybeToString (VNR vn vc) = (versionNumberWithMaybeToString vn) ++ "." ++ (maybeToString vc) 
versionNumberWithMaybeToString (VC vc) = (maybeToString vc) 

Gibt es eine ähnliche Standard-Bibliothek-Implementierung, die für das Parsen von Strings in dieser Datenstruktur und Umwandlung zwischen rechten und linken Darstellungen ermöglichen würde? Ich würde mich über Kommentare/Ideen zu diesem Thema freuen. Danke im Voraus!

PS. Ich brauche die Optionen VNL und VNR, damit ich die Versionsnummern folgendermaßen vergleichen kann: x.x.3 == x.3 == 3. Ich gehe davon aus nur VNR Version zu diesem Zweck arbeiten:

instance Eq VersionNumberWithMaybe where 
    (VC vc1) == (VC vc2) = (vc1 == vc2) 
    (VNL vc1 vn1) == (VNL vc2 vn2) = (vc1 == vc2 && vn1 == vn2) 
    (VNR vn1 vc1) == (VNR vn2 vc2) = (vc1 == vc2 && vn1 == vn2) 

    (VNL _ (VC vc1)) == (VC vc2) = vc1 == vc2 
    (VC vc1) == (VNL _ (VC vc2)) = vc1 == vc2 

    (VNR _ vc1) == (VC vc2) = vc1 == vc2 
    (VC vc1) == (VNR _ vc2) = vc1 == vc2 

diese Definition von Eq Angesichts Vergleiche folgenden funktioniert wie beabsichtigt fein:

VNR (VNR (VC Nothing) Nothing) (Just 3) == VNR (VC Nothing) (Just 3) -- x.x.3 == x.3 -> True 
VNR (VC Nothing) (Just 3) == VC (Just 3) -- x.3 == 3 -> True 

Während mit VNL es wird nicht wie vorgesehen als es wird erlauben, dass solche Vergleiche wie 3.x.x == 3.x -> True stattfinden

PS2. Vielen Dank für Ihre Kommentare. Ich fange an zu überdenken, ob ich wirklich beide und VNL (und nicht nur, zum Beispiel VNL) brauche, um zu erreichen, was ich will. Ich evaluiere, welcher Ansatz besser ist, nur einen zu lassen und dieses ganze conversion_between_representations Kopfweh zu vermeiden.

+0

Sie haben das rekursiv ausgeführt, was bedeutet, dass Sie möglicherweise Versionsnummern wie 1.0.0.0.0.0.0.0.0.0.0 haben können – Emil

+0

Ist es nicht seltsam, dass Sie Versionsnummern wie 'x.2' haben können? –

+0

@WillemVanOnsem Es ist ein bisschen komisch, aber auf der anderen Seite gibt es Projekte, wo das eine Bedeutung hat. Zum Beispiel gibt es vielleicht eine Richtlinie, dass ungerade nummerierte Nebenversionen Bugfix-Releases sind und sogar Inhalts-Patches sind. – amalloy

Antwort

2

Für Versionsnummern darstellen, als eine Folge von ganzen Zahlen durch Punkte getrennt definiert, kann man einfach eine Liste von ganzen Zahlen verwenden, anstatt ihre eigene Liste Art der Umsetzung:

newtype LTRVersion = MkLTRVersion { unLTRVersion :: [Int] } 
    deriving (Show, Eq, Ord) 

versionToString = intercalate "." . map show . unLTRVersion 

Dies erlaubt beliebige Versionen der Form „xyz "für eine beliebige Anzahl von Versions-Chunks". Die richtige Bestellbeziehung ist ableitbar, was praktisch ist.

(Man könnte denken, dass natürliche Zahlen eine präzisere Darstellung darstellen, aber Haskell lässt Sie gerne einen Laufzeitfehler generieren, indem Sie eine größere Zahl von einer kleineren Zahl subtrahieren, so dass YMMV. Int ebenfalls verfügbar ist . entweder das Vorspiel, während natürliche Zahlen sind nicht)

das von rechts nach links Versionsschema zu implementieren, kann man eine snoC Liste oder umgekehrt die Liste zu Vergleichszwecken (mit comparing von Data.Ord) verwenden:

newtype RTLVersion = MkRTLVersion { unRTLVersion :: [Int] } 

instance Ord RTLVersion where 
    compare = comparing (reverse . unRTLVersion) 

Allerdings beide nur zulassen integrale Versionsnummern. Mehr willkürlich ist:

newtype Version = MkVersion [Either Int String] 
    deriving (Show, Eq) 

mit

instance Ord Version 

und

versionToString :: Version -> String 

als Übungen für den Leser überlassen.

Eine weitere Verallgemeinerung für Versionsnummern mit fehlenden „Chunks“ jeden Brocken wie eventuell vorhandenen darstellen kann:

newtype MayVersion = MkMayVersion [Maybe Int] 

Ich bin nicht sicher, was die Semantik zeigt, das entspricht oder diese Versionen zu vergleichen wäre, damit ich Ich rate nicht bei einer Implementierung.

Es könnte auch nützlich sein Maybe Int mit einem gleichwertigen Typ zu ersetzen, die Namen verwendet, die im Problembereich von Bedeutung sind:

data Chunk = Imaginary | Known Int 

newtype MayVersion = MkMayVersion [Chunk] 

Es ist auch möglich sein kann, durch deren Umsetzung Eq und Ord auf MayVersion herzuleiten Chunk.

Für extrem willkürliche Begriffe der Versionierung (z. B. solche, die "@" oder andere Trennzeichen als "." Beinhalten können) bietet das versions Paket eine Art Version, die amüsant Complex Mess genannt wird. Es würde jedoch nur "imaginäre" Versions-Chunks ad hoc unterstützen.

Ich sollte auch erwähnen, dass die Kombination von LTR und RTL Cons Zellen in der gleichen Listenstruktur durch Konstruktion falsch scheint, so habe ich es nicht berücksichtigt. Was bedeutet

VNL Nothing (VNR Nothing (VC (Just 1)) 

zu sein? Eine Version, die sowohl auf RTL als auch auf LTR läuft, scheint für mich einfach ungültig zu sein. Wenn Sie für beide eine Datenstruktur haben wollen, können Sie

data Version 
    = LTR LTRVersion 
    | RTL RTLVersion 

kombinieren, die sicherstellt, dass beiden Versionstypen durch die Konstruktion richtig sind (na ja, sind unendlich Versionsnummern nicht verhindert, aber anders als das). Mir ist jedoch nicht klar, wie eine LTR-Version und eine RTL-Version miteinander verglichen werden sollen, daher bin ich mir nicht sicher, ob dies tatsächlich gewünscht ist.

+0

Danke für Ihre ausführliche Antwort! Bitte überprüfen Sie meine bearbeitete Frage, da ich den Link zu der visuellen Darstellung hinzugefügt habe, die ich in Haskell darzustellen versuche. Ich habe auch erklärt, warum ich LTR- und RTL-Versionen brauche. Hoffentlich finden Sie das hilfreich. BTW, du meintest wahrscheinlich 'VNL Nothing (VNR (VC Nothing) (nur 1))' in deiner 'zu sein' Frage. Die Antwort darauf wäre die Version 'x.x.1', die ein legitimes Konstrukt in meiner Versionsnummerierung ist. – altern

+0

Warum sollte 'x.x.1 'sei' VNL Nichts (VNL Nichts (VC (Nur 1))) '? Ich verstehe nicht, 'VNL' mit' VNR' zu mischen. –

Verwandte Themen