andro
andro

Reputation: 939

Haskell wildcard symbol usage

In the source code for the Applicative instance for Maybe we have:

instance Applicative Maybe where
pure = Just

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

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

I had thought that '_' is used as a wildcard in patterns. What is the meaning here therefore of '_m' and '_m2' values? Is this a GHC coding convention? Is there some performance advantage to not using _?

Upvotes: 4

Views: 2343

Answers (2)

Antal Spector-Zabusky
Antal Spector-Zabusky

Reputation: 36622

You're right that _ is a wildcard. What you see here are just variables with names beginning with _; there's no special syntax. Both _ and variables match any value, but _ signals that you're ignoring that value. Consequently, GHC will warn you if you define a variable and don't use it, which comes in handy. But what if you want to document what you're ignoring, without being warned that you're ignoring it? Well, _ is just another word character in Haskell, so you can begin a variable name with it. And GHC will assume that any _-initial variable names you defined are intended to be unused, and refrain from warning you about them.

Thus, in

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

The _m is used to be clear that it's the same thing as the m above, but isn't being used. If we replaced it with _, that might be less clear. And if we replaced it with m, we'd get a warning:

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

In general, _ is only a little bit special in Haskell pattern matches. Besides the "no warnings" property above (which doesn't change what the program does, only the compiler messages), matching against _ is almost exactly like matching against any other variable. There are only two differences:

  1. You can match against multiple _s at once.

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

    Every _ is distinct – two underscores are not the same thing as each other. However, when we match against variables, all the variables we match against have to be distinct; you can't match against "x" twice. (You can sort of think of _ as a variable whose name is different each time.)

  2. You can't use _ in expressions, only in patterns.

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

    Because _ doesn't "remember" what it matched against, as we saw above, you can never use it in an expression. It's only ever a pattern.

Upvotes: 3

Sibi
Sibi

Reputation: 48654

If you don't use the _ prefix, you will get warning when compiling:

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’

You can use _ to avoid the warnings. So, _var is used to give a name to the variable and to avoid warning. You can do something like this:

Justa m1 *> _m      = _m

But with wildcards, you cannot do something like this:

Just m1 *> _ = _

Upvotes: 1

Related Questions