Frage

Vor einiger Zeit habe ich einen gefragt Frage zu $, und bekam nützliche Antworten – tatsächlich dachte ich, ich hätte verstanden, wie man es benutzt.

Scheinbar habe ich mich geirrt :(

Dieses Beispiel erscheint in einem Tutorial:

instance Monad [] where
   xs >>= f = concat . map f $ xs

Ich kann mir beim besten Willen nicht vorstellen, warum dort $ verwendet wurde;ghci hilft mir auch nicht, da selbst Tests, die ich dort durchführe, eine Gleichwertigkeit mit der Version zu zeigen scheinen, bei der das $ einfach weggelassen wurde.Kann mir das jemand klären?

War es hilfreich?

Lösung

Die $ wird hier verwendet, weil es eine geringere Priorität als normale Funktion Anwendung hat. Eine weitere Möglichkeit, diesen Code zu schreiben, ist wie folgt:

instance Monad [] where
   xs >>= f = (concat . map f) xs

Die Idee dabei ist es, zunächst eine Funktion (concat . map f) zu konstruieren und dann gilt es auf ihr Argument (xs). Wie gezeigt, kann dies auch indem man einfach Klammer um den ersten Teil durchgeführt werden.

Beachten Sie, dass der $ in der ursprünglichen Definition Weglassen nicht möglich ist, wird es in einem Typfehler zur Folge hat. Dies liegt daran, die Funktion Zusammensetzung Operator (die .) eine niedrigere Priorität als normale Funktion Anwendung hat effektiv den Ausdruck in drehen:

instance Monad [] where
  xs >>= f = concat . (map f xs)

Welche keinen Sinn macht, weil das zweite Argument der Funktion Zusammensetzung Operator keine Funktion überhaupt ist. Obwohl die folgende Definition macht Sinn:

instance Monad [] where
  xs >>= f = concat (map f xs)

Dies ist übrigens auch die Definition, die ich würde es vorziehen, weil es mir scheint, viel klarer zu sein.

Andere Tipps

Ich mag erklären, warum IMHO ist dies nicht der verwendete Stil dort:

instance Monad [] where
  xs >>= f = concat (map f xs)

concat . map f ist ein Beispiel für so genannte pointfree-Stil Schreiben; wo pointfree bedeutet „ohne den Punkt der Anwendung“. Denken Sie daran, dass in der Mathematik, in dem Ausdruck y=f(x), wir sagen, dass f auf den Punkt x angewendet wird. In den meisten Fällen können Sie tatsächlich einen letzten Schritt tun, zu ersetzen:

f x = something $ x

mit

f = something

wie f = concat . map f, und das ist eigentlich pointfree Stil. Welches ist klarer diskutierbar ist, aber der pointfree Stil einen anderen Blickwinkel gibt, die auch nützlich ist, so manchmal verwendet wird, auch wenn sie nicht genau benötigt wird.

EDIT:. Ich habe ersetzt sinnlos mit pointfree und einige Beispiele festgelegt, nach dem Kommentar von Alasdair, den ich danken soll

Der Grund, warum $ hier verwendet wird, liegt an der Typsignatur von (.):

(.) :: (b -> c) -> (a -> c) -> a -> c

Hier haben wir

map f :: [a] -> [[b]]

Und

concat :: [[b]] -> [b]

Also am Ende haben wir

concat . map f :: [a] -> [b]

und der Typ von (.) könnte geschrieben werden als

(.) ::([[b]] ​​-> [b]) -> ([a] -> [[b]]) -> [a] -> [b]

Wenn wir verwenden würden concat . map f xs, das würden wir sehen

map f xs :: [[b]]

Und kann daher nicht mit (.) verwendet werden.(Der Typ müsste (.) sein:(a -> b) -> a -> b

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top