2016-04-06 4 views
0

Wie Sie wissen bereits, wenn Sie Karte verwenden sie eine Funktion recibes und diese Funktion auf jedes Element derHaskell: Invertierung ‚Karte‘

map f xs is the list obtained by applying f to each element of xs, i.e., 

Aber in meinem Fall Liste gelten habe ich eine Liste von Funktionen y müssen auf einen bestimmten Wert angewendet werden. Dies sind die Arten, um eine bessere Vorstellung zu geben:

data Auto = Auto {plate :: String, currentTank :: Int, tanqSize :: Int} deriving (Show, Eq) 
type Services = Car -> Car 
service :: Car -> [Services] -> Car 

Wie ich vor [Dienstleistungen] erklärt wird eine Liste von Funktionen, die ‚Auto‘ und Rückkehr ‚Car‘ recibe. Ich muss diese Funktionen auf das "Auto" anwenden, das "Service" rezitiert und es mit allen durchgeführten Änderungen zurückgibt.

Hier sind einige Beispiele von Funktionen in der Liste angezeigt:

emptyTank :: Services 
reFuel :: Int -> Services 
changePlate :: String -> Services 
upgradeTank :: Int -> Services 

Kennt jemand einen Weg, dies zu lösen? Für den Fall, dass Sie eine geeignetere Funktion kennen, um die Karte zu verwenden, sagen Sie es mir und ich werde mich darum kümmern.

+0

Suche nach '$', 'flip' und currying. – PyRulez

+4

Mögliches Duplikat von [Haskell: Mapping-Funktion-Anwendung] (http://stackoverflow.com/questions/13134857/haskell-mapping-function-application) – amalloy

+3

Dies ist kein Duplikat des Vorschlags; 'service' muss ein einzelnes' Car' zurückgeben, nicht eine Liste des Typs '[Car]'. – chepner

Antwort

2

Sie können foldl für diesen Einsatz:

service :: Car -> [Services] -> Car 
service car functions = foldl (flip ($)) car functions 

service someCar [emptyTank, (refuel 10), (changePlate "abc 123"), (upgradeTank 15)] 

($) Funktion Anwendung, aber es mit foldl zu verwenden (die Funktionen in der richtigen Reihenfolge anwenden, müssen wir ihre Argumente drehen, so dass arg $ f ausgewertet f arg. mit (flip ($)) mit foldl wird die erste Funktion in functions bewirken car, dann wird die zweite Funktion auf das Ergebnis der ersten, dann die dritte auf das Ergebnis des zweiten usw.

012.351 aufgebracht werden

(foldr könnte mit einfach ($) anstelle von flip ($) verwendet werden, aber es würde die Funktionen von rechts nach links, nicht von links nach rechts anwenden. Vergleichen

foldl (flip ($)) 3 [(+4), (*5)] -- Returns (3+4)*5 = 35 

mit

foldr ($) 3 [(+4), (*5)] -- Returns (3*5) + 4 = 19 

)


Ein anderer Weg, dies zu betrachten, ist, dass Sie Ihre Liste von Funktionen in einer Funktion zusammenstellen wollen:

(upgradeTank 15) . (changePlate "abc 123") . (refuel 10) . emptyTank $ someCar 

was Sie auch tun können foldl (oder foldr? Es scheint keinen Unterschied zu machen, welchen Sie hier verwenden.) Verwenden Sie (.), um die Liste auf eine einzelne Funktion zu reduzieren, und wenden Sie dann diese Funktion auf car an. Die id-Funktion wird als das andere Argument für den ersten Aufruf von (.) von foldl verwendet. Sie müssen die Liste der Funktionen jedoch zuerst umkehren, da die Komposition rechtsassoziativ ist.

service car functions = foldl (.) id (reverse functions) $ car 
+0

Danke, hier ist, wie ich verwendet, was Sie mir gesagt haben: Services (Autoplatte currentTanq tanqSize) Liste = foldl (flip ($)) Liste (Car plate currentTanq tanqSize) Liste – Marco