Ich muss foo n = maximumBy (comparing p) [1..n]
berechnen, wobei p :: Int -> Int
langsam ist. Aber ich weiß, dass p n < n
für alle n > 0
und möchte diese Tatsache verwenden, um diese Berechnung auf folgende Weise zu beschleunigen: Ich berechne p x
für x
beginnend mit n
bis 1
, das aktuelle Maximum zu speichern. Sobald ich ein x
erreiche weniger oder gleich dem aktuellen Maximum, weiß ich, dass dieses Maximum das globale sein muss und ich fertig bin.Idiomatic Haskell Code zur Vereinfachung der Rekursion
So sieht mein Versuch wie folgt aus:
foo n = go (0, 0) n where
go (c, _) 1 = c
go (c, c') !x = if c' >= x then c else go (c2, c'2) (x-1) where
x' = p x
(c2, c'2) = if c' >= x' then (c, c') else (x, x')
Dies funktioniert, aber sieht nicht sehr idiomatisch. Ich suche also eine elegantere Lösung. Hast du Vorschläge?
Sie sich von dem Paar zu befreien, machen 'es xyn gehen ...', und ich würde binden 'pn' zu einem Namen (don geben Sie dem Compiler nicht einmal die Möglichkeit, den Wert neu zu berechnen, sonst würde ich das tun. Einfach, klar, effizient. –
Danke, ersetzen Sie das Paar, wie Sie vorgeschlagen, es ist definitiv besser. Wie dem auch sei, ich muss zugeben, dass ich über eine Verwendung von Let ... in Binding zögere, da ich wirklich nicht weiß, ob in meinem zweiten Pattern-Matching das (pn) zweimal berechnet wird oder nicht. Wenn ich meinen Code rechtfertigen muss, würde ich argumentieren, dass Haskell von Natur aus faul ist. Dies bedeutet, dass die Evaluierungsstrategie Call-by-Need ist und per Definition "Call-by-Need ist eine memoisierte Version von Call-by-Name". dann sollte es in Ordnung sein, nein? Da es wahr ist, dass die Verwendung einer angebundenen Bindung, wie Sie es vorgeschlagen haben, keinen Platz für Zweifel lässt, habe ich Ihren Vorschlag unter meinen hinzugefügt. – zurgl
Ich würde ein 'wo' verwenden. 'geh 'x y n | n == 1 || n <= y = x | pn> y = gehe n pn (n-1) | sonst = gehe xy (n-1) wobei pn = pn'. –