2014-11-01 6 views
5

Ich arbeite an einigen Code für ein Kartenspiel:Ist Schreiben Helferfunktionen für die staatlichen Übertragungsstil idiomatischen in Haskell?

splitCards_ (x:xs) (a,b,c) | isGold x = splitCards xs (a:x,b,c) 
          | isAction x = splitCards xs (a,b:x,c) 
          | isVP x  = splitCards xs (a,b,c:x) 
splitCards_ [] (a,b,c) = (a,b,c) 

splitCards xs = splitCards_ xs ([],[],[]) 

Wesentlichen eine Liste der Karten nehmen und es in drei verschiedene Listen aufzuteilen von der Art der Karte abhängig. splitCards_ stellt Statusaktualisierungen durch rekursiv es die Parameter zu aktualisieren, dann splitCards (die eigentliche Funktion) verwendet wird, um immer die Berechnung mit den drei Listen von bestimmten Arten von Karten leer zu beginnen.

Ich glaube, das heißt State-Passing-Stil, und ich bin mir ziemlich sicher, dass das vollkommen idiomatische ist, aber ich bin mehr besorgt mit der Tatsache, dass ich eine Hilfsfunktion splitCards_ definieren müssen, um dies zu arbeiten wie ich will. Erschafft Hilfsfunktionen wie diese idiomatische Haskell? Gibt es eine sauberere Möglichkeit, dies zu schreiben? Sind Benennungskonventionen vorzuziehen, nur einen Unterstrich am Ende des Namens der Hilfsfunktion anzubringen?

Antwort

8

Ja, das ist ein perfekt idiomatischer Stil. Es ist ein klassischer Weg, um eine Funktion Tail rekursiv zu machen. (Obwohl das in Haskell weniger wichtig und etwas nuancierter ist).

Darüber hinaus ist die Herstellung von Hilfsfunktionen definitiv gut und ein wichtiger Teil viele gemeinsame Muster. Wenn Sie das Gefühl haben, dass etwas natürlicher ist, sollten Sie es tun! Wenn es nicht extrem ist, hilft es Lesbarkeit.

Der Hauptvorschlag ich habe, ist die Hilfsfunktion in eine where Klausel setzen. Auf diese Weise wird es nur im Rahmen der Hauptfunktion sichtbar, die deutlich macht, dass es nur ein Helfer ist. Der Name, den Sie der Hilfsfunktion geben, ist weniger wichtig; splitCards_ ist in Ordnung, aber splitCards' (ausgesprochen "splitCards Prime") und go (ein generischer Name für Hilfsfunktionen) wäre häufiger. So würde ich den Code so etwas wie dies umschreiben:

splitCards xs = go xs ([],[],[]) 
    where go (x:xs) (a, b, c) | isGold x = go xs (a:x,b,c) 
          | isAction x = go xs (a,b:x,c) 
          | isVP x  = go xs (a,b,c:x) 
     go [] (a, b, c) = (a, b, c) 

Beachten Sie, dass diese sind nur kosmetische Änderungen-was Sie tun, ist grundsätzlich Sound.

Die zwei Namensoptionen (go vs splitCards') ist nur eine Frage der Präferenz.

Ich persönlich mag go weil, sobald Sie an die Konvention gewöhnt sind, es deutlich signalisiert, dass etwas nur eine Hilfsfunktion ist. In gewissem Sinne ist go fast eher wie Syntax als eine Funktion seines eigenen; es ist Bedeutung der splitCards Funktion rein untergeordnet ist.

Andere mögen nicht go, weil es ein wenig kryptisch und etwas willkürlich ist. Es kann auch die rekursive Struktur Ihres Codes weniger klar machen, da Sie auf go und nicht die Funktion selbst rekursiv sind.

Gehen Sie für alles, was Sie denken, am besten aussieht.

3

Ich habe nicht viel zu Antwort des @ Tichon hinzuzufügen, außer dass in diesem speziellen Fall, dass Sie die partition Funktion von Data.List verwenden:

splitCards xs = 
    let (as,bs) = partition isGold xs 
     (cs,ds) = partition isAction bs 
    in (as,cs,ds) -- (golds, actions, others) 

Aufgrund lazy evaluation es im Wesentlichen die gleiche Leistung wie die Hand haben sollte Version

1

Im allgemeinen Fall ist Code wie Ihres idiomatisch, besonders wenn es etwas aufgeräumt ist, wie @Tichon vorgeschlagen hat. Im konkreten Fall scheint Ihr Rekursionsschema eine linke Falte zu sein, daher wird es normalerweise im Code explizit gemacht. Aufbauend auf @ Tichons Code:

splitCards xs = foldl' separate ([],[],[]) xs 
    where separate (a, b, c) x | isGold x = (a:x,b,c) 
          | isAction x = (a,b:x,c) 
          | isVP x  = (a,b,c:x) 

Die erste Zeile kann sogar eta vergebene sein (nicht viel benötigt in diesem Fall meiner Meinung nach, aber ...)

splitCards = foldl' separate ([],[],[]) 
    where ... 
Verwandte Themen