2017-05-09 30 views
4

在對應用型實例的源代碼,也許我們有:哈斯克爾通配符使用

instance Applicative Maybe where 
pure = Just 

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

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

我原以爲「_」用作模式通配符。這裏'_m'和'_m2'的含義是什麼?這是GHC編碼慣例嗎?沒有使用_有一些性能優勢嗎?

回答

3

你說得對,_是一個通配符。你在這裏看到的只是名稱以_開頭的變量;沒有特別的語法。 _和變量都匹配任何值,但_表示您忽略該值。因此,如果您定義了一個變量並且不使用它,GHC會警告您,這很方便。但是,如果你想記錄什麼你忽略,而沒有被警告你忽略它?那麼,_只是Haskell中的另一個單詞字符,所以你可以用它開始一個變量名。 GHC將假定您定義的任何_-初始變量名稱是意圖未被使用,並且避免警告您有關它們。

因此,在

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

_m用於明確的是,這是同樣的事情上面m,但不被使用。如果我們用_代替它,那可能不太清楚。如果我們用m取代它,我們會得到一個警告:

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

一般來說,_只是有點特殊哈斯克爾模式匹配。除了上面的「無警告」屬性(它不會改變程序的功能,只有編譯器的消息),匹配_幾乎完全像是與任何其他變量相匹配。只有兩點區別:

  1. 您可以一次匹配多個_ s。

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

    _是截然不同的 - 兩個下劃線是不一樣的東西對方。但是,當我們與變量匹配時,我們所匹配的所有變量必須是不同的;你不能與「x」匹配兩次。 (您可以將_視爲每次變量名稱不同的變量)。

  2. 不能在表達式中使用_,只能在模式中使用。

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

    因爲_不會「記住」它匹配的反對,正如我們上面所看到的,你永遠不能在表達式中使用它。這只是一種模式。

1

如果不使用_前綴,則編譯時得到警告:

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’ 

您可以使用_避免警告。因此,_var用於給變量命名並避免警告。你可以做這樣的事情:

Justa m1 *> _m  = _m 

但隨着通配符,你不能做這樣的事情:

Just m1 *> _ = _ 
+0

但是下劃線變量沒有在RHS上使用? – andro

+0

@andro在你的具體例子中,沒關係。使用'_'等同於'_var'。但總的來說,它們有所不同。 – Sibi