Frage Was ist der Sinn von 'const' im Haskell Prelude?


Durch das Haskell Prelude schauend, ich Siehe eine Funktion  const:

const x _ = x

Ich kann nichts Relevantes über diese Funktion finden.

Was ist der Punkt? Kann jemand ein Beispiel geben, wo diese Funktion verwendet werden könnte?


75
2017-09-13 13:17


Ursprung


Antworten:


Es ist nützlich für die Übergabe an Funktionen höherer Ordnung, wenn Sie nicht alle ihre Flexibilität benötigen. Zum Beispiel der monadische Sequenzoperator >> kann in Bezug auf den monadischen Bindeoperator als definiert werden

x >> y = x >>= const y

Es ist etwas besser als mit einem Lambda

x >> y = x >>= \_ -> y

und Sie können es sogar punktfrei verwenden

(>>) = (. const) . (>>=)

obwohl ich das in diesem Fall nicht besonders empfehle.


70
2017-09-13 13:20



Um Hammars ausgezeichnete direkte Antwort hinzuzufügen: bescheidene Funktionen wie const und id sind aus dem gleichen Grund, aus dem sie sind, als Funktion höherer Ordnung nützlich grundlegend in dem SKI Kombinator Kalkül.

Nicht dass ich denke, Haskells Vorspielfunktionen wurden bewusst nach diesem formellen System oder irgendetwas modelliert. Es ist nur so, dass das Erstellen von reichen Abstraktionen in Haskell sehr einfach ist, so dass Sie diese Art von theoretischen Dingen oft als praktisch nützlich erscheinen sehen.

Schamloser Stecker, aber ich habe darüber gebloggt, wie die Applicative-Instanz funktioniert (->) sind eigentlich die S und K Kombinierer Hier, wenn es das ist, woran du bist.


24
2017-09-13 14:40



Ein einfaches Beispiel für die Verwendung const ist Data.Functor.(<$). Mit dieser Funktion können Sie sagen: Ich habe hier einen Funktor mit etwas Langweiligem darin, aber stattdessen möchte ich das andere interessante Ding darin haben, ohne die Form des Funktors zu ändern. Z.B.

import Data.Functor

42 <$ Just "boring"
--> Just 42

42 <$ Nothing
--> Nothing

"cool" <$ ["nonsense","stupid","uninteresting"]
--> ["cool","cool","cool"]

Die Definition lautet:

(<$) :: a -> f b -> f a
(<$) =  fmap . const

oder nicht als sinnlos geschrieben:

cool <$ uncool =  fmap (const cool) uncool

Du siehst wie const wird hier verwendet, um die Eingabe zu "vergessen".


21
2017-09-14 08:30



Ich kann nichts Relevantes über diese Funktion finden.

Viele der anderen Antworten diskutieren relativ esoterische (zumindest für den Neuling) Anwendungen von const. Hier ist eine einfache: Sie können verwenden const um ein Lambda loszuwerden, das zwei Argumente braucht, wirft das erste weg, tut aber etwas Interessantes mit dem zweiten.

Zum Beispiel die folgende (ineffiziente!) Implementierung von length,

length' = foldr (\_ acc -> 1 + acc) 0

kann als neu geschrieben werden

length' = foldr (const (1+)) 0

Das ist vielleicht eleganter.

Der Ausdruck const (1+) ist in der Tat gleichwertig \_ acc -> 1 + acc, weil es ein Argument benötigt, es wegwirft und den Abschnitt zurückgibt (1+).


14
2018-02-12 20:49



Eine weitere Verwendung besteht darin, Klassenmemberfunktionen 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:

instance Bits Int where
  isSigned = const True
  bitSize  = const wordSize
  ...

Mit const sagen wir explizit, 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 nette Art, Instanzen zu schreiben.


12
2017-09-14 09:25



const möglicherweise nur die Implementierung, die Sie in Verbindung mit anderen Funktionen suchen. Hier ist ein Beispiel, das ich entdeckt habe.

Nehmen wir an, wir wollen eine Struktur von 2-Tupeln in eine andere Struktur von 2-Tupeln umschreiben. Ich könnte dies so ausdrücken:

((a,b),(c,d)) ⇒ (a,(c,(5,a)))

Ich kann eine geradlinige Definition mit Mustererkennung geben:

f ((a,b),(c,d)) = (a,(c,(5,a)))

Was, wenn ich eine sinnlose (implizite) Lösung für diese Art von Umschreibungen möchte? Einige denken und fummeln später, die Antwort ist, dass wir alle umschreiben können mit (&&&), const, (.), fst, snd. Beachten Sie, dass (&&&) aus Control.Arrow.

Die Lösung des Beispiels, das diese Funktionen verwendet, ist:

(fst.fst &&& (fst.snd &&& (const 5 &&& fst.fst)))

Beachten Sie die Ähnlichkeit mit (a,(c,(5,a))). Was ist, wenn wir ersetzen &&& mit ,? Dann heißt es:

(fst.fst, (fst.snd, (const 5, fst.fst)))

Beachte wie a ist das erste Element des ersten Elements, und das ist was fst.fst Projekte. Beachte wie c ist das erste Element des zweiten Elements, und das ist was fst.snd Projekte. 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 Applicativ verallgemeinert, so dass Sie jede Funktion in einem sinnlosen Stil schreiben können (solange Sie die Fallanalyse als Funktionen zur Verfügung haben, wie z maybe, either, bool). Nochmal, const spielt die Rolle der Einführung von Konstanten. Sie können diese Arbeit in der sehen Data.Function.Tacit Paket.

Wenn Sie abstrakt, am Ziel beginnen und dann auf eine Implementierung hinarbeiten, können Sie von den Antworten überrascht werden. Das heißt, jede einzelne Funktion kann so mysteriös sein wie irgendein Zahnrad in einer Maschine. Wenn Sie jedoch zurückziehen, um die gesamte Maschine in Sicht zu bringen, können Sie den Kontext verstehen, in dem diese Kogge notwendig ist.


2
2018-06-13 19:21