The underscore character is treated in almost all cases like a letter. It can therefore be used anywhere within an identifier. Although the conventional way to form an identifier from multiple words in Haskell is “camelCase”, you can define names in "snake_case" if you wish:
But the underscore also has some special meanings. Often an underscore character in Haskell code represents something we don’t care about or don’t know about – whether it’s a wildcard, a hole, or a discarded result. Underscores appear both in types and in terms. Sometimes they have some special meaning in the language; other times they may be part of some informal naming convention.
When the underscore appears alone in a pattern, This is perhaps the most common use of an underscore. it is a reserved identifier that acts as a wildcard: a pattern that matches anythingA pattern that always succeeds is called an irrefutable pattern. but does not introduce a new variable.
“Pattern” includes function parameters. So when an underscore is used as one of the formal parameters of a function, it idiomatically conveys that this function does not care about its argument. Such a function is constant:
The following definition of
Maybe uses an underscore in the
Nothing case because the function is irrelevant when there is nothing to apply it to:
An underscore often appears as the last entry in a case expression as a catch-all that matches when everything else has failed:
As a prefix
The underscore character is treated like a lowercase letter. This means that it can be the first character of function names and variables, but not the first character of classes and types.See Identifiers and operators for a fuller discussion of the significance of capitalization. Beginning a name with an underscore is sometimes used to name variables we will not use – and thus don’t really care about – but care just enough about to give it a name to remind ourselves of what is being discarded.
Unlike a standalone underscore, this underscore is not a keyword, and
greetCasually does bind a variable named
_lastName which you can make reference to. The only thing the underscore does is suppress a compiler warning about an unused variable.
Underscores may appear alone to indicate a hole, at the type or term level, whose presence will elicit type information from the compiler.
-fdefer-typed-holes GHC flag enabled, this is a warning instead of an error.
As a prefix
An identifier may begin with an underscore, and this carries no special significance. Doing so is atypical.
-fdefer-typed-holes, if the identifier is undefined, then it is interpreted as a hole rather than a reference to an undefined variable.
As a suffix
There is a similar-but-different convention for putting an underscore at the end of a function name; functions like this typically come as part of a pair of similar functions, where the one with the underscore is simpler in some way, usually because it discards some value. A good example from
base is traversal:
The first applies a function to each element of a collection and returns a collection of the results. The second applies a function to each element of a collection, accumulating its “effects”, but does not collect the results.
PartialTypeSignatures extension enabled, an underscore may appear within a type signature.
As a prefix
A name like “
_a” is normally a valid name for a type variable. If you enable the
NamedWildCards extension, then it becomes a hole instead.
As a constraint
PartialTypeSignatures, GHC will not infer a constraint unless you add a wildcard to the constraint list.
In the output of :sprint
When you use the
:sprint command in GHCi, it uses an underscore to represent parts of the value that are yet unevaluated.