Was ist der Unterschied zwischen dem Punkt (.)
und dem Dollarzeichen ($)
?
Soweit ich weiß, handelt es sich bei beiden um syntaktischen Zucker, da keine Klammern verwendet werden müssen.
quelle
Was ist der Unterschied zwischen dem Punkt (.)
und dem Dollarzeichen ($)
?
Soweit ich weiß, handelt es sich bei beiden um syntaktischen Zucker, da keine Klammern verwendet werden müssen.
Der $
Operator dient zum Vermeiden von Klammern. Alles, was danach erscheint, hat Vorrang vor allem, was vorher kommt.
Angenommen, Sie haben eine Zeile mit der Aufschrift:
putStrLn (show (1 + 1))
Wenn Sie diese Klammern entfernen möchten, würde eine der folgenden Zeilen dasselbe tun:
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
Der Hauptzweck des .
Operators besteht nicht darin, Klammern zu vermeiden, sondern Funktionen zu verketten. Damit können Sie die Ausgabe von allem, was rechts angezeigt wird, mit der Eingabe von allem, was links angezeigt wird, verknüpfen. Dies führt normalerweise auch zu weniger Klammern, funktioniert aber anders.
Zurück zum selben Beispiel:
putStrLn (show (1 + 1))
(1 + 1)
hat keine Eingabe und kann daher nicht mit dem .
Operator verwendet werden.show
kann ein nehmen Int
und ein zurückgeben String
.putStrLn
kann ein nehmen String
und ein zurückgeben IO ()
.Sie können verketten, show
um putStrLn
dies zu mögen:
(putStrLn . show) (1 + 1)
Wenn das zu viele Klammern für Ihren Geschmack sind, entfernen Sie sie mit dem $
Operator:
putStrLn . show $ 1 + 1
putStrLn . show . (+1) $ 1
wäre so etwas gleichwertig. Sie haben insofern Recht, als die meisten (alle?) Infix-Operatoren Funktionen sind.map ($3)
. Ich meine, ich$
vermeide meistens auch Klammern, aber es ist nicht so, dass das alles ist, wofür sie da sind.map ($3)
ist eine Funktion des TypsNum a => [(a->b)] -> [b]
. Es nimmt eine Liste von Funktionen, die eine Nummer annehmen, wendet 3 auf alle an und sammelt die Ergebnisse.Sie haben unterschiedliche Typen und unterschiedliche Definitionen:
($)
soll die normale Funktionsanwendung ersetzen, jedoch mit einer anderen Priorität, um Klammern zu vermeiden.(.)
dient zum Zusammensetzen von zwei Funktionen, um eine neue Funktion zu erstellen.In einigen Fällen sind sie austauschbar, dies gilt jedoch im Allgemeinen nicht. Das typische Beispiel, wo sie sind, ist:
==>
Mit anderen Worten, in einer Kette von
$
s können alle bis auf die letzte durch ersetzt werden.
quelle
x
eine Funktion wäre? Können Sie dann.
als letzte verwenden?x
in diesem Kontext bewerben , dann ja - aber dann würde sich der "letzte" auf etwas anderes als bewerbenx
. Wenn Sie sich nicht bewerbenx
, unterscheidet es sich nichtx
davon, ein Wert zu sein.Beachten Sie auch, dass
($)
es sich um die auf Funktionstypen spezialisierte Identitätsfunktion handelt . Die Identitätsfunktion sieht folgendermaßen aus:Während
($)
sieht so aus:Beachten Sie, dass ich der Typensignatur absichtlich zusätzliche Klammern hinzugefügt habe.
Verwendungen von
($)
können normalerweise durch Hinzufügen von Klammern beseitigt werden (es sei denn, der Operator wird in einem Abschnitt verwendet). ZB:f $ g x
wirdf (g x)
.Verwendungen von
(.)
sind oft etwas schwerer zu ersetzen; Sie benötigen normalerweise ein Lambda oder die Einführung eines expliziten Funktionsparameters. Zum Beispiel:wird
wird
Hoffe das hilft!
quelle
($)
Ermöglicht die Verkettung von Funktionen ohne Hinzufügen von Klammern zur Steuerung der Bewertungsreihenfolge:Der Compose-Operator
(.)
erstellt eine neue Funktion, ohne die Argumente anzugeben:Das obige Beispiel ist wohl illustrativ, zeigt aber nicht wirklich die Bequemlichkeit der Verwendung von Komposition. Hier ist eine andere Analogie:
Wenn wir den dritten nur einmal verwenden, können wir vermeiden, ihn mit einem Lambda zu benennen:
Schließlich lässt uns die Komposition das Lambda vermeiden:
quelle
Die kurze und süße Version:
($)
Ruft die Funktion, die das linke Argument ist, für den Wert auf, der das rechte Argument ist.(.)
setzt die Funktion, die das linke Argument ist, mit der Funktion zusammen, die das rechte Argument ist.quelle
Eine Anwendung, die nützlich ist und für die ich einige Zeit gebraucht habe, um aus der sehr kurzen Beschreibung bei learn you a haskell herauszufinden : Seit:
und die Klammerung der rechten Seite eines Ausdrucks, der einen Infix-Operator enthält, konvertiert ihn in eine Präfixfunktion, zu der man
($ 3) (4+)
analog schreiben kann(++", world") "hello"
.Warum sollte jemand das tun? Zum Beispiel für Funktionslisten. Beide:
und:
sind kürzer als
map (\x -> x ++ ", world") ...
odermap (\f -> f 3) ...
. Offensichtlich wären die letzteren Varianten für die meisten Menschen besser lesbar.quelle
$3
ohne den Platz zu verwenden. Wenn Template Haskell aktiviert ist, wird dies als Spleiß analysiert, während dies$ 3
immer bedeutet, was Sie gesagt haben. Im Allgemeinen scheint es in Haskell einen Trend zu geben, Syntaxbits zu "stehlen", indem darauf bestanden wird, dass bestimmte Operatoren Leerzeichen um sich haben, die als solche behandelt werden sollen.Sie sind kein syntaktischer Zucker, weil sie keine Klammern verwenden müssen - sie sind Funktionen -, die angefügt sind, daher können wir sie Operatoren nennen.
Verfassen Sie,
(.)
und wann Sie es verwenden sollen.(.)
ist die Compose-Funktion. Damitist die gleiche Funktion wie ein Gebäude, das aufgrund seines Arguments gibt weitergegeben
g
auff
.Verwenden
(.)
Sie diese Option, wenn Sie nicht über die verfügbaren Argumente verfügen, um sie an die Funktionen zu übergeben, die Sie erstellen möchten.Es gilt der richtige Assoziativ
($)
und wann er verwendet werden soll($)
ist eine rechtsassoziative Apply-Funktion mit geringer Bindungspriorität. Es berechnet also nur die Dinge rechts davon zuerst. Somit,ist prozedural dasselbe (was wichtig ist, da Haskell träge bewertet wird, wird es
f
zuerst zu bewerten beginnen ):oder genauer:
Verwenden
($)
Sie diese Option, wenn Sie alle zu bewertenden Variablen haben, bevor Sie die vorhergehende Funktion auf das Ergebnis anwenden.Wir können dies sehen, indem wir die Quelle für jede Funktion lesen.
Lesen Sie die Quelle
Hier ist die Quelle für
(.)
:Und hier ist die Quelle für
($)
:Fazit
Verwenden Sie die Komposition, wenn Sie die Funktion nicht sofort bewerten müssen. Vielleicht möchten Sie die Funktion, die sich aus der Komposition ergibt, an eine andere Funktion übergeben.
Verwenden Sie die Anwendung, wenn Sie alle Argumente für eine vollständige Bewertung angeben.
In unserem Beispiel wäre dies semantisch vorzuziehen
wenn wir
x
(oder besser gesagtg
) Argumente haben und tun:wenn wir es nicht tun.
quelle
... oder Sie könnten die
.
und$
Konstruktionen durch Pipelining vermeiden :Das ist, nachdem Sie in der Hilfsfunktion hinzugefügt haben:
quelle
$
Betreiber eigentlich mehr wie F # funktioniert 's ,<|
als es tut|>
, in der Regel in Haskell würden Sie die obige Funktion wie folgt schreiben:third xs = head $ tail $ tail $ xs
oder vielleicht sogar wiethird = head . tail . tail
, was in F # -Stil Syntax etwas so sein würde:let third = List.head << List.tail << List.tail
$
ist bereits verfügbar und heißt&
hackage.haskell.org/package/base-4.8.0.0/docs/…Eine gute Möglichkeit, mehr über irgendetwas (jede Funktion) zu erfahren, besteht darin, sich daran zu erinnern, dass alles eine Funktion ist! Dieses allgemeine Mantra hilft, aber in bestimmten Fällen wie bei Operatoren hilft es, sich an diesen kleinen Trick zu erinnern:
und
Denken Sie daran,
:t
großzügig zu verwenden , und wickeln Sie Ihre Bediener ein()
!quelle
Meine Regel ist einfach (ich bin auch Anfänger):
.
wenn Sie den Parameter übergeben möchten (Funktion aufrufen), und$
wenn noch kein Parameter vorhanden ist (Funktion erstellen)Das ist
aber nie:
quelle
Ich denke, ein kurzes Beispiel dafür, wo Sie verwenden würden
.
und nicht,$
würde helfen, die Dinge zu klären.Beachten Sie, dass dies
times6
eine Funktion ist, die aus der Funktionszusammensetzung erstellt wird.quelle
Alle anderen Antworten sind ziemlich gut. Es gibt jedoch ein wichtiges Usability-Detail darüber, wie ghc $ behandelt, das der ghc-Typprüfer die Instatiarion mit höherrangigen / quantifizierten Typen ermöglicht. Wenn Sie sich
$ id
zum Beispiel den Typ von ansehen, werden Sie feststellen, dass er eine Funktion annehmen wird, deren Argument selbst eine polymorphe Funktion ist. Kleinigkeiten wie diese haben nicht die gleiche Flexibilität wie ein gleichwertiger verärgerter Bediener. (Das lässt mich tatsächlich fragen, ob $! Die gleiche Behandlung verdient oder nicht)quelle