2010-07-04 9 views
18

Welche der folgenden werden Sie am ehesten schreiben?Haskell Karte/Zip Vs. Liste Verständnis

r = zip xs $ map sqrt xs 

oder

r = [(x, sqrt x) | x <- xs] 

Beispielcode im Internet scheint darauf hinzudeuten, dass die ehemalige reichliche und der bevorzugte Weg ist.

Antwort

9

ich wahrscheinlich

map (\x -> (x, sqrt x)) xs 

schreiben würden, wenn Sie Punkt frei bevorzugen, ist das oben entspricht (nach

map (ap (,) sqrt) xs 

Eine weitere Alternative, die‚Control.Monad und Control.Monad.Instances) eingeführt haben hasn Noch nicht erwähnt wurde

zipWith (,) xs (map sqrt xs) 
6

Ich verwende selten List Comprehensions, aber beide sind dandy. Verwenden Sie einfach den, der Ihren Code leichter lesbar macht.

23

Menschen, die zu viel Zeit in #haskell verbringen würde wahrscheinlich, dass als

schreiben
r = map (id &&& sqrt) xs 

(&&&) ein Spaß combinator in Control.Arrow definiert ist. Seine tatsächliche Typ-Signatur ist kompliziert, weil sie auf alle Instanzen von Arrow verallgemeinert wird. Aber es ist oft mit der (->) Instanz Arrow verwendet, die in dieser Art Signatur ergibt:

(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c) 
+7

Ich bezeichne dies als "undurchsichtiges Haskell". An einem bestimmten Punkt ist es nur unleserlich, der Punkt variiert bei der Belichtung. – Dan

+1

Tatsächlich tendiere ich dazu, eine Funktion zu definieren, die ich aus Mangel an einem besseren Namen 'bewahren :: (a -> b) -> a -> (a, b)', definiert als einfach 'conservating = (id &&&) '. (Manchmal tausche ich auch die Tupelreihenfolge und definiere sie als '(&& & id)'; Ich sollte konsistent sein.) Ich bin immer ein wenig überrascht, dass es nirgends Standard zu verlassen scheint. –

+8

Dan, ich denke, das ist wahrscheinlich das Einfachste Pfeil-Kombinator, um in echten Code zu verwenden.Sein Name ist schön evokativ: Sie können diese Codezeile laut lesen als "map id und sqrt to xs". – Carl

15

Obwohl ich neige dazu, sie nicht verwenden sehr häufig, in diesem Fall denke ich, dass ich die Liste Verständnis Version bevorzugen würde, weil es mir sauberer erscheint.

Wenn Sie in Punkt freie Art sind, können 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 verallgemeinert Anwendung in SKI calculus:

ap f g x == f x (g x) 
ap const const == id 

Wie Conal weist darauf hin, dies auch aus Monad verallgemeinert werden kann thusly (import Control.Applicative) applikative:

f = zip <*> map sqrt 
+1

schön, ich mag diese Notation am besten. Ich lese immer "ap" als "apply", also wird es: "zip apply map mit sqrt zur Eingabe" – Dan

+2

Oder vereinfachend/generalisierend von 'Monad' zu' Applicative', 'f = zip <*> map sqrt'. Obwohl ich persönlich bevorzuge "map (id && & sqrt) xs" wie in Carls Antwort. – Conal

+0

Ja, das ist IMHO eine nette Art, es zu lesen. @Conal hat Ihren Vorschlag der Antwort hinzugefügt. – danlei

11

Ich würde wahrscheinlich map/zip schreiben und später wünschte ich hätte das Listenverständnis geschrieben.

9

Für bestimmte Arten von Problemen (Project Euler), insbesondere dieser spezielle Fall kommt so oft, dass ich die folgenden kleinen Helfer schrieb:

with :: (a -> b) -> a -> (a,b) 
with f a = (a, f a) 

Diese Ihr Beispiel erlaubt geschrieben werden:

r = map (with sqrt) xs 
6

Ich bin eher eine "Old School" Haskellier, also würde ich zip `ap` map sqrt verwenden und später es umgestalten, um die <*> statt ap zu verwenden.

Applikativ ist die neue Monade. (Im Sinne von "Was benutzen die Cool Haskell Kids heutzutage?„)

+3

Pfeile sind die neue Monade, nein? –