Zur kulturellen und intellektuellen Bereicherung habe ich beschlossen, ein wenig Haskell zu lernen. Ich habe Hugh's "Why Functional Programming Matters" gelesen hier lesen und versuche, den Code in echtes Haskell zu übersetzen. Ich habe hier meinen Versuch angehängt (für die numerischen Teile des Papiers; der Alpha-Beta-Algorithmus ist noch interessanter, aber ich müsste auch einen Spielbewerter von Grund auf schreiben!).
Bis jetzt war es eher ein Übung in der Haskell-Syntax als alles andere. Ich habe bereits einfache Dinge wie die Übersetzung von repeat
in das native Haskell iterate
, die Übersetzung einiger Funktionen, die viele Klammern verwendet haben, in Funktionskomposition (wodurch sie im Prozess mehr punktfrei wurden), usw., gemacht.
Aber mein Code funktioniert sicherlich, und ich frage mich, ob er ausreichend "haskellhaft" ist. Können mir Experten dort draußen einige Hinweise geben?
-- 4.1 Newton-Raphson-Quadratwurzeln
next n x = (x + n/x)/2.0
-- -- Dies ist "iterate::(a->a)->a->[a]"
-- wiederholen f a = a : iterate f (f a)
within eps (a:b:rest) =
if abs(a-b) <= eps
then b
else within eps (b:rest)
sqroot a0 eps n = within eps (iterate (next n) a0)
relative eps (a:b:rest) =
if abs(a-b) <= eps*abs(b)
then b
else relative eps (b:rest)
relativesqrt a0 eps n = relative eps (iterate (next n) a0)
-- 4.2 numerische Differenzierung
easydiff f x h = (f (x+h) - f x) / h
differentiate h0 f x = map (easydiff f x) (iterate (/2) h0)
-- diff1a h0 eps f x = within eps (differentiate h0 f x)
diff1 h0 eps f = within eps . differentiate h0 f
elimerror n (a:b:rest) = (b*(2**n)-a)/(2**n-1) : elimerror n (b:rest)
-- benötigen fromIntegral, um aus dem Int, der von round herauskommt, einen Nicht-Integer zu machen
order (a:b:c:rest) = fromIntegral (round (logBase 2 ((a-c)/(b-c)-1)))
improve s = elimerror (order s) s
--diff2a h0 eps f x = within eps (improve (differentiate h0 f x))
diff2 h0 eps f = within eps . improve . differentiate h0 f
--super s = map second (iterate improve s) -- wie können wir das punktfrei machen?
super :: (RealFrac t, Floating t) => [t] -> [t]
-- ohne dies will es [double]->[double] sein
super = map second . iterate improve
-- second (a:b:rest) = b
second = head . tail
diff3 h0 eps f = within eps . super . differentiate h0 f
-- 4.3 Integration
easyintegrate f a b = (f a + f b)*(b-a)/2
-- addpair wird zu (uncurry (+))
integrate f a b = integ f a b (f a) (f b)
integ f a b fa fb =
(fa+fb)*(b-a)/2 : map (uncurry (+)) (zip (integ f a m fa fm) (integ f m b fm fb))
where m = (a+b)/2
fm = f m
-- Test: Das Folgende sollte etwa pi sein
approxpi eps = within eps (improve (integrate (\x -> 4/(1+x*x)) 0 1))
superpi eps = within eps (super (integrate (\x -> 4/(1+x*x)) 0 1))
-- Gibt es eine Möglichkeit, die Anzahl der Iterationen im Auge zu behalten? Status-Monad, aber das scheint wie viel Arbeit...\
0 Stimmen
Die letzte Bearbeitung von @Juliet scheint das Beispiel ab dem inneren Teil (innerhalb :) vermasselt zu haben.
0 Stimmen
Ja, bemerkt und behoben. Ich habe jetzt "pre" entfernt, da es den Text durcheinander gebracht hat; werde mit schlechter Syntaxhighlightung leben müssen. Ist das ein Fehler???
0 Stimmen
Ja, das Syntax-Highlighting von StackOverflow ist für Haskell schlecht. Wenn man sich Uservoice ansieht, scheint es, dass
codinghorror
(Jeff Atwood) wie üblich alle Fehlerberichte schnell als "abgelehnt" schließt. Wahrscheinlich ist der einzige Weg, um das zu beheben, direkt an die Quelle zu berichten: code.google.com/p/google-code-prettify1 Stimmen
Wenn du hier fertig bist, wäre es gut, wenn du das, was du gemacht hast, in der Haskell-Mailingliste postest - eine Haskell-Version von "Why Functional Programming Matters" würde von vielen sehr geschätzt werden!
0 Stimmen
Ja, die Haskell-Färbung funktioniert nicht. Aber eigentlich war das eigentliche Problem das "pre"-Tag, das tatsächlich einige Texte im Code gelöscht hat.
1 Stimmen
Wenn Sie verwenden, müssen Sie trotzdem HTML-Entitätsreferenzen im Text verwenden, z. B. "<" anstelle von "<".