Recursive state-Monade für die Akkumulation von Wert, während den Aufbau einer Liste?

Ich bin vollkommen neu in Haskell also entschuldigt, wenn die Frage ist dumm.

Was ich will zu tun ist, rekursiv eine Liste aufbauen, während gleichzeitig Aufbau eines akkumulierten Wertes basiert auf der rekursiven Aufrufe. Dies ist für ein problem, ich mache für einen Coursera-Kurs, damit ich nicht nach den genauen problem, aber etwas analoges.

Sagen Sie zum Beispiel, wollte ich eine Liste von ints und Doppel jeweils (ohne Berücksichtigung der für die Zwecke des Beispiels, dass ich konnte einfach map), aber ich auch wollte zählen, wie viele Male die Zahl '5' in der Liste erscheint.

Damit zu tun, die Verdoppelung könnte ich dies tun:

foo []     = []
foo (x:xs) = x * 2 : foo xs

So weit, So einfach. Aber wie kann ich auch pflegen Sie eine zu zählen, wie viele Male x ist eine fünf? Die beste Lösung, die ich habe, ist die Verwendung eines expliziten Akkumulators wie diese, die ich nicht mag, wie es kehrt die Liste, also müssen Sie tun, ein reverse-am Ende:

foo total acc []     = (total, reverse acc)
foo total acc (x:xs) = foo (if x == 5 then total + 1 else total) (x*2 : acc) xs

Aber ich fühle mich wie dieser sollte in der Lage sein, um behandelt werden schöner durch die State Monade, die ich nicht verwendet haben, bevor, aber wenn ich versuche, eine Funktion zu konstruieren, passen die Muster, die ich gesehen habe, bekomme ich stecken bleiben, weil der rekursiven Aufruf foo. Gibt es eine schönere Art, dies zu tun?

EDIT: muss ich diese Arbeit für sehr lange Listen, so dass jede rekursive Aufrufe werden müssen tail-recursive zu. (Das Beispiel habe ich hier verwaltet werden tail-rekursive Dank Haskell 's" tail recursion modulo cons').

  • Verwandte Frage: "Tail-Optimierung - Garantie- loop-Codierung in Haskell".
  • In welchem Sinne ist dein Beispiel tail-rekursiv? Ich glaube, dass es sich thunks und bewirkt, dass ein "memory leak". Selbst ein einfacher Aufruf reverse genug zu sein scheint, um einen Speicherverlust verursachen.
  • Wenn ich sage, es ist tail-rekursive, ich meinte die einfache Karte Beispiel, nicht die zweite code-fragment. TBH ich habe eine harte Zeit, herauszufinden, was ist und was nicht effizienten code in Haskell - es scheint zu funktionieren völlig anders als jede andere Sprache, die ich verwendet habe! Glaube, ich brauche zu tun, etwas mehr darüber zu Lesen 🙂
InformationsquelleAutor Russell | 2013-07-07
Schreibe einen Kommentar