Wenn ich durch das Haskell-Präludium schaue, sehe ich eine Funktionconst
:
const x _ = x
Ich kann anscheinend nichts Relevantes zu dieser Funktion finden.
Was ist der Punkt? Kann jemand ein Beispiel geben, wo diese Funktion verwendet werden könnte?
backgroundColor :: Text -> Color
ist für michbackgroundColor = const White
Antworten:
Dies ist nützlich, um Funktionen höherer Ordnung zu übergeben, wenn Sie nicht die gesamte Flexibilität benötigen. Beispielsweise kann der monadische Sequenzoperator
>>
in Bezug auf den monadischen Bindungsoperator als definiert werdenEs ist etwas ordentlicher als ein Lambda
und Sie können es sogar punktfrei verwenden
obwohl ich das in diesem Fall nicht besonders empfehle.
quelle
map (const 42) [1..5]
ergibt sich[42, 42, 42, 42, 42]
.const
ist nützlich, um auf ein einzelnes Argument anzuwenden, um eine Funktion zu erhalten, bei der eine benötigt wird (z. B. Übergabe anmap
).head = foldr const (error "Prelude.head: empty list")
Um die ausgezeichnete direkte Antwort von Hammar zu ergänzen: Demütige Funktionen mögen
const
undid
sind als Funktion höherer Ordnung aus demselben Grund wirklich nützlich, aus dem sie in der SKI-Kombinatorrechnung von grundlegender Bedeutung sind .Nicht, dass ich denke, dass Haskells Vorspielfunktionen bewusst diesem formalen System oder irgendetwas nachempfunden waren. Es ist nur so, dass das Erstellen umfangreicher Abstraktionen in Haskell sehr einfach ist. Daher sehen Sie diese Art von theoretischen Dingen oft als praktisch nützlich an.
Schamloser Plug, aber ich habe darüber gebloggt, wie die Applicative-Instanz
(->)
tatsächlich dieS
undK
Kombinatoren hier sind , wenn Sie so etwas mögen.quelle
((->) e)
ist auch die Lesermonade - mitReader
und dergleichen nurnewtype
Wrapper - und dieask
Funktion ist dannid
, also ist das auch derI
Kombinator. Wenn Sie sich stattdessen die ursprüngliche BCKW-Basis von Haskell Curry ansehenB
,K
undW
sindfmap
,return
undjoin
jeweils.Ein einfaches Beispiel für die Verwendung
const
istData.Functor.(<$)
. Mit dieser Funktion kann man sagen: Ich habe hier einen Funktor mit etwas Langweiligem, aber stattdessen möchte ich das andere interessante Ding darin haben, ohne die Form des Funktors zu ändern. Z.BDie Definition lautet:
oder nicht so sinnlos geschrieben:
Sie sehen, wie
const
hier verwendet wird, um die Eingabe zu "vergessen".quelle
Viele der anderen Antworten diskutieren relativ esoterische (zumindest für den Neuling) Anwendungen von
const
. Hier ist eine einfache: Sie können verwendenconst
ein Lambda loswerden, das zwei Argumente akzeptiert, das erste wegwirft, aber mit dem zweiten etwas Interessantes macht.Zum Beispiel die folgende (ineffiziente, aber lehrreiche) Implementierung von
length
:kann umgeschrieben werden als
das ist vielleicht eleganter.
Der Ausdruck
const (1+)
ist in der Tat semantisch äquivalent zu\_ acc -> 1 + acc
, da er ein Argument nimmt, es wegwirft und den Abschnitt zurückgibt(1+)
.quelle
Eine andere Verwendung besteht darin, Klassenelementfunktionen zu implementieren, die ein Dummy-Argument haben, das nicht ausgewertet werden sollte (zum Auflösen mehrdeutiger Typen). Beispiel, das in Data.bits sein könnte:
Mit const sagen wir ausdrücklich, dass wir konstante Werte definieren.
Persönlich mag ich die Verwendung von Dummy-Parametern nicht, aber wenn sie in einer Klasse verwendet werden, ist dies eine ziemlich gute Art, Instanzen zu schreiben.
quelle
const
Möglicherweise ist dies nur die Implementierung, nach der Sie in Verbindung mit anderen Funktionen suchen. Hier ist ein Beispiel, das ich entdeckt habe.Angenommen, wir möchten eine Struktur von 2-Tupeln in eine andere Struktur von 2-Tupeln umschreiben. Ich könnte dies so ausdrücken:
Ich kann eine einfache Definition mit Mustervergleich geben:
Was ist, wenn ich eine sinnlose (stillschweigende) Lösung für diese Art von Umschreibungen möchte? Einige denken und fummeln später, die Antwort ist, dass wir alle Umschreibungen mit ausdrücken können
(&&&), const, (.), fst, snd
. Beachten Sie, dass von(&&&)
istControl.Arrow
.Die Lösung des Beispiels mit diesen Funktionen lautet:
Beachten Sie die Ähnlichkeit mit
(a,(c,(5,a)))
. Was passiert , wenn wir ersetzen&&&
mit,
? Dann heißt es:Beachten Sie, wie
a
das erste Element des ersten Elements ist und wasfst.fst
Projekte sind. Beachten Sie, wiec
das erste Element des zweiten Elements ist und wasfst.snd
Projekte sind. Das heißt, Variablen werden zum Pfad zu ihrer Quelle.const
erlaubt uns, Konstanten einzuführen. Interessant, wie der Name mit der Bedeutung übereinstimmt!Ich habe dann diese Idee mit Applicative verallgemeinert , so dass Sie jede Funktion in einem sinnlosen Stil schreiben kann (so lange , wie Sie als Funktionen Fallanalyse zur Verfügung haben, wie
maybe
,either
,bool
). Wiederconst
spielt die Rolle der Einführung von Konstanten. Sie können diese Arbeit im Data.Function.Tacit- Paket sehen.Wenn Sie abstrakt am Ziel beginnen und dann auf eine Implementierung hinarbeiten, können Sie von den Antworten überrascht sein. Das heißt, jede Funktion kann so mysteriös sein wie jedes Zahnrad in einer Maschine. Wenn Sie sich jedoch zurückziehen, um die gesamte Maschine sichtbar zu machen, können Sie den Kontext verstehen, in dem dieses Zahnrad erforderlich ist.
quelle
Angenommen, Sie möchten eine Liste erstellen
Nothings
, die der Länge einer Zeichenfolge entspricht. Daconst
das erste Argument zurückgegeben wird, können Sie unabhängig vom zweiten Folgendes tun:oder genauer gesagt:
quelle
Angenommen, Sie möchten eine Liste drehen. Dies ist eine idiomatische Methode in Haskell:
rotate :: Int -> [a] -> [a] rotate _ [] = [] rotate n xs = zipWith const (drop n (cycle xs)) xs
Diese Funktion komprimiert zwei Arrays mit der Funktion
const
, wobei das erste ein unendliches zyklisches Array und das zweite das Array ist, mit dem Sie begonnen haben.const
fungiert als Grenzüberprüfung und verwendet das ursprüngliche Array, um das zyklische Array zu beenden.Siehe: Eine Liste in Haskell drehen
quelle
Angenommen, Sie möchten alle Teilsequenzen einer bestimmten Liste generieren.
Für jedes Listenelement haben Sie an einem bestimmten Punkt die Wahl zwischen True (in die aktuelle Teilsequenz aufnehmen) oder False (nicht einschließen). Dies kann mit der Funktion filterM erfolgen .
So was:
Zum Beispiel wollen wir alle Teilsequenzen von
[1..4]
.quelle