Ich bin völlig neu zu Haskell so Entschuldigungen, wenn die Frage albern ist.Rekursive Status-Monade zum Akkumulieren eines Wertes beim Erstellen einer Liste?
Was ich tun möchte, ist rekursiv erstellen Sie eine Liste, während gleichzeitig Aufbau eines akkumulierten Werts auf der Grundlage der rekursiven Aufrufe. Das ist für ein Problem, das ich für einen Coursera-Kurs mache, also werde ich das genaue Problem aber etwas analoges nicht posten.
Sagen Sie zum Beispiel ich eine Liste von ints und Doppeln jeden (ohne Berücksichtigung für die Zwecke des Beispiels, das ich gerade map
verwenden könnte) nehmen wollte, aber ich auch wollte die Zahl "zählen, wie oft 5 'erscheint in der Liste.
So die Verdoppelung tun ich dies tun könnte:
foo [] = []
foo (x:xs) = x * 2 : foo xs
So weit, so einfach. Aber wie kann ich auch zählen, wie oft x
eine fünf ist? Die beste Lösung, die ich habe ist einen expliziten Speicher wie diese zu verwenden, was Ich mag es nicht, wie es die Liste umkehrt, so müssen Sie am Ende eines umgekehrt tun:
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 Dies sollte besser mit der Monade State
gehandhabt werden, die ich vorher nicht benutzt habe, aber wenn ich versuche, eine Funktion zu konstruieren, die zu dem Muster passt, das ich gesehen habe, bleibe ich wegen des rekursiven Aufrufs an foo
hängen. Gibt es einen schöneren Weg, dies zu tun?
EDIT: Ich brauche das für sehr lange Listen zu arbeiten, so dass alle rekursiven Aufrufe tail-recursive auch sein müssen. (Das Beispiel, das ich hier habe, schafft es dank Haskells "Tail Recursion Modulo Cons", tailrekursiv zu werden).
damit verbundene Frage: [ "Schwanz Optimierung Garantie - Loop-Codierung in Haskell"] (http://stackoverflow.com/q/9149183/ 849891). –
In welchem Sinne ist Ihr Beispiel Tail rekursiv? Ich glaube, dass es Thunks anhäuft und ein "Speicherleck" verursacht. Schon der Aufruf von "reverse" reicht aus, um ein Speicherleck zu verursachen. – yairchu
Wenn ich sage * es ist * tail recursive, meinte ich das einfache Map-Beispiel, nicht das zweite Codefragment. TBH Ich habe eine harte Zeit herauszufinden, was ist und was nicht effizienter Code in Haskell ist - es scheint völlig anders zu funktionieren als jede andere Sprache, die ich benutzt habe! Ich denke, ich muss noch mehr darüber lesen :-) – Russell