Haskell Karte / zip Vs. Liste Verständnis
-
02-10-2019 - |
Frage
Welche der folgenden sind Sie am ehesten zu schreiben?
r = zip xs $ map sqrt xs
oder
r = [(x, sqrt x) | x <- xs]
Beispielcode im Internet scheint darauf hinzudeuten, dass die ehemalige reichliche und die bevorzugte Art und Weise ist.
Lösung
Ich würde wahrscheinlich schreiben
map (\x -> (x, sqrt x)) xs
Wenn Sie Punkt frei bevorzugen, die oben entspricht (nach Control.Monad
und Control.Monad.Instances
eingeführt haben)
map (ap (,) sqrt) xs
Eine weitere Alternative, die noch nicht erwähnt ist
zipWith (,) xs (map sqrt xs)
Andere Tipps
Die Menschen, die zu viel Zeit in #haskell verbringen würde wahrscheinlich schreiben, wie
r = map (id &&& sqrt) xs
(&&&)
ist ein Spaß combinator in Control.Arrow
definiert. Seine eigentliche Art Signatur ist kompliziert, weil es für alle Instanzen von Pfeil verallgemeinert wird. Aber es ist oft mit der (->)
Instanz Arrow
, die Ergebnisse in dieser Art Signatur verwendet:
(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)
Obwohl ich neige dazu, sie nicht sehr häufig zu verwenden, in diesem Fall denke ich, dass ich die Liste Verständnis Version bevorzugen würde, da es sauberer ich scheint.
Wenn Sie in Punkt freie Art sind, könnten Sie dieses mögen, auch:
f = zip `ap` map sqrt
ap Leben in Control.Monad und in diesem Fall kann es als S combinator gedacht werden, die Anwendung verallgemeinert in SKI Kalkül :
ap f g x == f x (g x)
ap const const == id
Wie Conal weist darauf hin, das auch von Monade zu Applicative verallgemeinert werden kann thusly (Import Control.Applicative):
f = zip <*> map sqrt
Ich würde wahrscheinlich schreiben map
/ zip
und dann später hatte ich wünsche, das Liste Verständnis geschrieben.
Für bestimmte Arten von Problemen ( Projekt Euler insbesondere ), dieser spezielle Fall kommt so oft, dass ich das schrieb folgende kleinen Helfer:
with :: (a -> b) -> a -> (a,b)
with f a = (a, f a)
Dies ermöglicht Ihr Beispiel geschrieben werden:
r = map (with sqrt) xs
Ich bin eher ein „Old School“ Haskellier, so dass ich zip `ap` map sqrt
verwenden würde und es später Refactoring die <*>
zu verwenden, anstatt ap
.
Applicative ist die neue Monade. (Im Sinne von „was der Cool Haskell Kinder nutzen diese Tage?“)
Ich verwende selten Listenkomprehensionen, aber beide sind Dandy. Verwenden Sie einfach die, die Ihren Code leichter macht zu lesen.