2016-10-12 6 views
4

finden Brandneu bei Haskell. Ich spiele mit der Fibonacci-Sequenz herum, um die Grundlagen der Sprache zu lernen, und ich kann den idiomatischen Weg nicht finden, etwas zu tun.Haskell Wert der konvergierenden Sequenz

fibs = 1 : 1 : zipWith (+) fibs (tail fibs) 

(Das ist schon ziemlich cool):

Die Fibonacci-Sequenz kann wie folgt definiert werden. Dann möchte ich die Sequenz verwenden, um das Goldene Verhältnis (Phi) zu approximieren. Also:

ratios = zipWith (/) (tail fibs) fibs 

ist eine Liste von immer besser Annäherungen an Phi. Nehmen wir an, ich möchte den ersten Wert erhalten, wenn die Liste sich unter einem gegebenen Schwellenwert epsilon "stabilisiert" hat. (dh die Differenz zwischen zwei aufeinanderfolgenden Werten von Verhältnissen ist kleiner als Epsilon). Ich kann sehen, wie ich das in einer imperativen Sprache machen würde (mit Hilfe von Indizes), aber wie würde man das in Haskell idiomatisch machen?

(Brauchen wir die folgende Liste benutzen? Aber wie?)

diffs = zipWith (-) ratios (tail ratios) 
+2

Hinweis: 'zip Verhältnisse diffs' eine Liste sein wird,' (Verhältnis, Derivat) 'Paare. Sie wollen [das erste Element finden] (http://hackage.haskell.org/package/base-4.9.0.0/docs/Prelude.html#v:dropWhile) in 'zip ratios diffs', für das die Ableitung ist unter der Schwelle. –

Antwort

3

Wie? Durch Verwendung eines anderen zip. Hier ist ein Einzeiler auf das, was Sie bereits haben:

snd . head . dropWhile (\(p1,p0) -> abs (p0 - p1) >= epsilon) $ zip ratio (tail ratio) 

von rechts nach links Lesen, das sagt:

  • zip zusammen die Liste der Verhältnisse mit ihren Nachfolgern
  • aus der Liste Wenn die Differenz zwischen den Verhältnissen größer ist als epsilon
  • Wenn dies erledigt ist, nehmen wir das erste Element der Liste und wählen den präziseren der beiden.
3

Eine Möglichkeit wäre list comprehensions zu verwenden:

getApprox threshold = head $ [ratio | (ratio, diff) <- zip (tail ratios) diffs 
            , abs diff < threshold 
          ]