2017-02-05 7 views
1

Angenommen, ich habe die folgende Funktionspeichern Variable und verwenden Sie es auf Rekursion

printVariance :: [Float] -> IO() 
printVariance [] = return() 
printVariance (x:xs) 
    | x >= avg (x:xs) = print (x - avg (x:xs)) >> printVariance xs 
    | otherwise  = printVariance xs 

, die eine Liste erhält, prüft, welche Elemente größer sind als der Durchschnitt und druckt ihre value - avg.

Mein Problem ist, dass der Wert avg jeden Schritt ändert. Wie kann ich es nur einmal definieren und seinen Wert für die Rekursion verwenden?

+2

Sie können dies mit Falten und Karten neu schreiben, anstatt direkt zu rekursiv. Dies würde es Ihnen ermöglichen, eine 'where' oder eine' let' Bindung anzuhängen, wobei Sie Ihren 'avg' als etwas definieren würden, das den Linien' (foldr (+) 0 xs)/length xs' entspricht. – Michail

Antwort

6

Verschieben Sie die Rekursion in eine Hilfsfunktion. Diese Funktion kann entweder den Durchschnitt als Parameter annehmen oder Sie können lokal printVariance definieren und eine andere lokale Variable definieren, die den Durchschnitt enthält, auf den die Funktion dann zugreifen könnte.

In Code:

printVariance :: [Float] -> IO() 
printVariance xs = loop xs 
    where 
    average = avg xs 
    loop [] = return() 
    loop (x:xs) 
     | x >= average = print (x - average) >> loop xs 
     | otherwise = loop xs 

PS: Es wäre gut, Entwurf des IO von der Programmlogik zu trennen. Also würde ich empfehlen, dass Sie Ihre Funktion einfach eine Liste der gewünschten Werte erstellen, anstatt sie zu drucken und das IO in eine separate Funktion zu verschieben (oder einfach main).

PPS: Sie berechnen nicht wirklich die Varianz, also würde ich empfehlen, die Funktion etwas anderes zu benennen.

+1

Ah, wir haben das gleiche Programm geschrieben. Ich werde meine Antwort aus Gründen der Kürze löschen :) – AJFarmar

+0

Sie haben es geschafft, ich weiß nicht, wie ich es nicht denken konnte, danke! –

Verwandte Themen