Beachten Sie, dass jeder Schritt loop
zwei Dinge gleichzeitig ausführt: Sie generieren (möglicherweise) eine Druckaktion aus jedem Element der Liste und kombinieren diese Aktion dann mit den verbleibenden (unter Verwendung von (>>)
). Wenn Sie loop
in Bezug auf map
schreiben möchten, müssen Sie diese beiden Unterschritte entwirren. Zum Beispiel können Sie eine Funktion definieren ...
printDiffIfAboveAvg :: Double -> IO()
... und es dann mit map printDiffIfAboveAvg
auf alle Elemente der Liste gelten. Das gibt Ihnen eine Liste von Aktionen, vom Typ [IO()]
, die Sie benötigen, um in eine einzige Gesamt Aktion kombinieren:
runAllActions :: [IO()] -> IO()
runAllActions
existiert bereits in der Basisbibliothek, in einer allgemeineren Version namens sequence_
:
sequence_ :: (Foldable t, Monad m) => t (m a) -> m()
So hätten Sie loop = sequence_ . map printDiffIfAboveAvg
. In der Tat ist es auch eine andere Funktion in der Basisbibliothek ...
mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m()
..., die genau diese Kombination von sequence_
und map
führt.
Eine gute Regel zu leben ist, so viel von Ihrem reinen Code wie möglich herauszufiltern. In diesem Sinne würde ich 'mapM_ print schreiben. foo wo foo = map (Durchschnitt subtrahieren). Filter (> Durchschnitt) '. Es hilft wirklich, die Arten von Dingen zu schreiben, die Sie bereits geschrieben haben, sowie die Arten der Dinge, die Sie schreiben möchten: Sie sagen also, Sie wollen 'map' verwenden, dann was ist der Typ der Funktion, die Sie beabsichtigen Pass auf 'map'? Es sieht nicht so aus, als hättest du so weit voraus gedacht – jberryman