2017-05-09 19 views
4

Im Quellcode für die Applicative Instanz für Vielleicht haben wir:Haskell Wildcard Symbol Verwendung

instance Applicative Maybe where 
pure = Just 

Just f <*> m  = fmap f m 
Nothing <*> _m  = Nothing 

Just _m1 *> m2  = m2 
Nothing *> _m2  = Nothing 

Ich hatte gedacht, dass ‚_‘ als Platzhalter in Mustern verwendet wird. Was bedeutet also hier die Werte von _m und _m2? Ist das eine GHC-Kodierungskonvention? Gibt es einen Leistungsvorteil, wenn Sie _ nicht verwenden?

Antwort

3

Du hast Recht, dass _ ein Platzhalter ist. Was Sie hier sehen, sind nur Variablen mit Namen beginnend mit _; Es gibt keine spezielle Syntax. Sowohl _ als auch Variablen entsprechen einem beliebigen Wert, aber _ signalisiert, dass Sie diesen Wert ignorieren. Folglich wird GHC Sie warnen, wenn Sie eine Variable definieren und nicht verwenden, was praktisch ist. Aber was, wenn Sie dokumentieren möchten, was Sie ignorieren, ohne gewarnt zu werden, dass Sie es ignorieren? Nun, _ ist nur ein weiteres Wort Zeichen in Haskell, so dass Sie einen Variablennamen damit beginnen können. Und GHC wird annehmen, dass alle von Ihnen definierten _-Anfangsvariablen intendiert sind, ungenutzt zu sein, und davon absehen, Sie über sie zu warnen.

So in

Just f <*> m = fmap f m 
Nothing <*> _m = Nothing 

Die _m wird klar sein, dass es die gleiche Sache wie die m oben ist, aber verwendet wird, nicht. Wenn wir es durch _ ersetzen, könnte das weniger klar sein. Und wenn wir es mit m ersetzt, würden wir eine Warnung erhalten:

…: warning: [-Wunused-matches] 
    Defined but not used: ‘m’ 

Im Allgemeinen _ ist nur ein wenig besondere in Haskell Muster übereinstimmt. Neben der obigen "no warnings" -Eigenschaft (die das, was das Programm tut, nur die Compiler-Nachrichten nicht ändert), ist das Vergleichen mit _ fast genau so, als würde es mit jeder anderen Variablen übereinstimmen. Es gibt nur zwei Unterschiede:

  1. Sie können gleichzeitig mit mehreren _ s übereinstimmen.

    star1, star2 :: a -> b -> Char 
    star1 _ _ = '*' 
    star2 x y = '*' 
    -- ILLEGAL: 
    -- star3 x x = '*' 
    

    Jeder _ unterscheidet - zwei Unterstrichen sind nicht das gleiche wie jeder andere. Wenn wir jedoch mit Variablen übereinstimmen, müssen alle Variablen, mit denen wir übereinstimmen, verschieden sein; Sie können nicht zweimal mit "x" übereinstimmen. (Sie können sich _ als Variable vorstellen, deren Name jedes Mal anders ist.)

  2. Sie können _ nicht in Ausdrücken verwenden, nur in Mustern.

    id2 :: a -> a 
    -- ILLEGAL: 
    -- id1 _ = _ 
    id2 x = x 
    

    Da _ nicht „erinnern“, was es abgeglichen, wie wir oben gesehen haben, können Sie es nie in einem Ausdruck verwenden. Es ist immer nur ein Muster.

1

Wenn Sie nicht das _ Präfix verwenden, werden Sie Warnung erhalten beim Kompilieren:

gcc -Wall test.hs: 

test.hs:21:18: Warning: Defined but not used: ‘m’ 

test.hs:23:11: Warning: Defined but not used: ‘m1’ 

test.hs:24:18: Warning: Defined but not used: ‘m2’ 

Sie _ verwenden können, die Warnungen zu vermeiden. So wird _var verwendet, um der Variablen einen Namen zu geben und eine Warnung zu vermeiden. Sie können etwas tun:

Justa m1 *> _m  = _m 

Aber mit Wildcards, können Sie so etwas wie dies nicht tun:

Just m1 *> _ = _ 
+0

Aber die Unterstreichungsvariable wird nicht auf der RHS verwendet? – andro

+0

@andro In Ihrem spezifischen Beispiel spielt es keine Rolle. Und '_' ist äquivalent zu' _var'. Aber im Allgemeinen unterscheiden sie sich. – Sibi