Haskell通配符符号用法

时间:2017-05-09 08:15:56

标签: haskell

在Maybe的Applicative实例的源代码中:

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编码惯例吗?不使用_?

是否有一些性能优势

2 个答案:

答案 0 :(得分:3)

你是对的_是通配符。您在此处看到的只是名称以_开头的变量;没有特殊的语法。 _和变量都匹配任何值,但_表示您忽略该值。因此,如果您定义变量并且不使用变量,GHC将警告您,这会派上用场。但是,如果您想记录您忽略的,而不是被警告您忽略它,该怎么办?好吧,_只是Haskell中的另一个单词字符,所以你可以用它开始一个变量名。 GHC将假设您定义的任何_ - 初始变量名称​​意图未使用,并且不会向您发出警告。

因此,在

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

_m用于表明它与上面的m相同,但未被使用。如果我们将其替换为_,则可能不太清楚。如果我们将其替换为m,我们会收到警告:

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

通常,_在Haskell模式匹配中只是有点特殊。除了上面的“无警告”属性(不改变程序所做的,只有编译器消息),与_匹配几乎完全匹配任何其他变量。只有两个不同之处:

  1. 您可以同时匹配多个_

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

    每个_都是不同的 - 两个下划线不是彼此相同的。但是,当我们匹配变量时,我们匹配的所有变量必须是不同的;你不能两次匹配“x”。 (您可以将_视为每次名称不同的变量。)

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

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

    因为_没有“记住”它匹配的内容,正如我们上面所见,你永远不能在表达式中使用它。它只是一种模式。

答案 1 :(得分: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 *> _ = _