DRAFT
This is a work in progress, not an official release of the Haskell 2010 Revised Language Report.
prev Contents next

3 Expressions

In this chapter, we describe the syntax and informal semantics of Haskell expressions, including their translations into the Haskell kernel, where appropriate. Except in the case of let expressions, these translations preserve both the static and dynamic semantics. Free variables and constructors used in these translations always refer to entities defined by the Prelude. For example, “concatMap” used in the translation of list comprehensions (Section 3.11) means the concatMap defined by the Prelude, regardless of whether or not the identifier “concatMap” is in scope where the list comprehension is used, and (if it is in scope) what it is bound to.

𝑒𝑥𝑝𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝::[𝑐𝑜𝑛𝑡𝑒𝑥𝑡=>]𝑡𝑦𝑝𝑒(expression type signature)
|𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝
𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝𝑙𝑒𝑥𝑝𝑞𝑜𝑝𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝
|-𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝(prefix negation)
|𝑙𝑒𝑥𝑝
𝑙𝑒𝑥𝑝\𝑎𝑝𝑎𝑡1𝑎𝑝𝑎𝑡𝑛->𝑒𝑥𝑝(lambda abstraction, 𝑛1)
|𝚕𝚎𝚝𝑑𝑒𝑐𝑙𝑠𝚒𝚗𝑒𝑥𝑝(let expression)
|𝚒𝚏𝑒𝑥𝑝[;]𝚝𝚑𝚎𝚗𝑒𝑥𝑝[;]𝚎𝚕𝚜𝚎𝑒𝑥𝑝(conditional)
|𝚌𝚊𝚜𝚎𝑒𝑥𝑝𝚘𝚏{𝑎𝑙𝑡𝑠}(case expression)
|𝚍𝚘{𝑠𝑡𝑚𝑡𝑠}(do expression)
|𝑓𝑒𝑥𝑝
𝑓𝑒𝑥𝑝[𝑓𝑒𝑥𝑝]𝑎𝑒𝑥𝑝(function application)
𝑎𝑒𝑥𝑝𝑞𝑣𝑎𝑟(variable)
|𝑔𝑐𝑜𝑛(general constructor)
|𝑙𝑖𝑡𝑒𝑟𝑎𝑙
|(𝑒𝑥𝑝)(parenthesized expression)
|(𝑒𝑥𝑝1,,𝑒𝑥𝑝𝑘)(tuple, 𝑘2)
|[𝑒𝑥𝑝1,,𝑒𝑥𝑝𝑘](list, 𝑘1)
|[𝑒𝑥𝑝1[,𝑒𝑥𝑝2]..[𝑒𝑥𝑝3]](arithmetic sequence)
|[𝑒𝑥𝑝|𝑞𝑢𝑎𝑙1,,𝑞𝑢𝑎𝑙𝑛](list comprehension, 𝑛1)
|(𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝𝑞𝑜𝑝)(left section)
|(𝑞𝑜𝑝-𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝)(right section)
|𝑞𝑐𝑜𝑛{𝑓𝑏𝑖𝑛𝑑1,,𝑓𝑏𝑖𝑛𝑑𝑛}(labeled construction, 𝑛0)
|𝑎𝑒𝑥𝑝𝑞𝑐𝑜𝑛{𝑓𝑏𝑖𝑛𝑑1,,𝑓𝑏𝑖𝑛𝑑𝑛}(labeled update, 𝑛1)

Expressions involving infix operators are disambiguated by the operator’s fixity (see Section 4.4.2). Consecutive unparenthesized operators with the same precedence must both be either left or right associative to avoid a syntax error. Given an unparenthesized expression “𝑥𝑞𝑜𝑝(𝑎,𝑖)𝑦𝑞𝑜𝑝(𝑏,𝑗)𝑧” (where 𝑞𝑜𝑝(𝑎,𝑖) means an operator with associativity 𝑎 and precedence 𝑖), parentheses must be added around either 𝑥𝑞𝑜𝑝(𝑎,𝑖)𝑦 or 𝑦𝑞𝑜𝑝(𝑏,𝑗)𝑧 when 𝑖=𝑗 unless 𝑎=𝑏=l or 𝑎=𝑏=r.

An example algorithm for resolving expressions involving infix operators is given in Section 10.6.

Negation is the only prefix operator in Haskell; it has the same precedence as the infix - operator defined in the Prelude (see Section 4.4.2, Figure 1).

The grammar is ambiguous regarding the extent of lambda abstractions, let expressions, and conditionals. The ambiguity is resolved by the meta-rule that each of these constructs extends as far to the right as possible.

Sample parses are shown below.

ThisParses as
f x + g y(f x) + (g y)
- f x + y(- (f x)) + y
let {...} in x + ylet {...} in (x + y)
z + let {...} in x + yz + (let {...} in (x + y))
f x y :: Int(f x y) :: Int
\ x -> a+b :: Int\x -> ((a+b) :: Int)

For the sake of clarity, the rest of this section will assume that expressions involving infix operators have been resolved according to the fixities of the operators.

3.1 Errors

Errors during expression evaluation, denoted by (“bottom”), are indistinguishable by a Haskell program from non-termination. Since Haskell is a non-strict language, all Haskell types include . That is, a value of any type may be bound to a computation that, when demanded, results in an error. When evaluated, errors cause immediate program termination and cannot be caught by the user. The Prelude provides two functions to directly cause such errors:

error     :: String -> a
undefined :: a

A call to error terminates execution of the program and returns an appropriate error indication to the operating system. It should also display the string in some system-dependent manner. When undefined is used, the error message is created by the compiler.

Translations of Haskell expressions use error and undefined to explicitly indicate where execution time errors may occur. The actual program behavior when an error occurs is up to the implementation. The messages passed to the error function in these translations are only suggestions; implementations may choose to display more or less information when an error occurs.

3.2 Variables, Constructors, Operators, and Literals

𝑎𝑒𝑥𝑝𝑞𝑣𝑎𝑟(variable)
|𝑔𝑐𝑜𝑛(general constructor)
|𝑙𝑖𝑡𝑒𝑟𝑎𝑙
𝑔𝑐𝑜𝑛()
|[]
|(,{,})
|𝑞𝑐𝑜𝑛
𝑣𝑎𝑟𝑣𝑎𝑟𝑖𝑑|(𝑣𝑎𝑟𝑠𝑦𝑚)(variable)
𝑞𝑣𝑎𝑟𝑞𝑣𝑎𝑟𝑖𝑑|(𝑞𝑣𝑎𝑟𝑠𝑦𝑚)(qualified variable)
𝑐𝑜𝑛𝑐𝑜𝑛𝑖𝑑|(𝑐𝑜𝑛𝑠𝑦𝑚)(constructor)
𝑞𝑐𝑜𝑛𝑞𝑐𝑜𝑛𝑖𝑑|(𝑔𝑐𝑜𝑛𝑠𝑦𝑚)(qualified constructor)
𝑣𝑎𝑟𝑜𝑝𝑣𝑎𝑟𝑠𝑦𝑚|`𝑣𝑎𝑟𝑖𝑑`(variable operator)
𝑞𝑣𝑎𝑟𝑜𝑝𝑞𝑣𝑎𝑟𝑠𝑦𝑚|`𝑞𝑣𝑎𝑟𝑖𝑑`(qualified variable operator)
𝑐𝑜𝑛𝑜𝑝𝑐𝑜𝑛𝑠𝑦𝑚|`𝑐𝑜𝑛𝑖𝑑`(constructor operator)
𝑞𝑐𝑜𝑛𝑜𝑝𝑔𝑐𝑜𝑛𝑠𝑦𝑚|`𝑞𝑐𝑜𝑛𝑖𝑑`(qualified constructor operator)
𝑜𝑝𝑣𝑎𝑟𝑜𝑝|𝑐𝑜𝑛𝑜𝑝(operator)
𝑞𝑜𝑝𝑞𝑣𝑎𝑟𝑜𝑝|𝑞𝑐𝑜𝑛𝑜𝑝(qualified operator)
𝑔𝑐𝑜𝑛𝑠𝑦𝑚:|𝑞𝑐𝑜𝑛𝑠𝑦𝑚

Haskell provides special syntax to support infix notation. An operator is a function that can be applied using infix syntax (Section 3.4), or partially applied using a section (Section 3.5).

An operator is either an operator symbol, such as + or $$, or is an ordinary identifier enclosed in grave accents (backquotes), such as `op`. For example, instead of writing the prefix application op x y, one can write the infix application x `op` y. If no fixity declaration is given for op then it defaults to highest precedence and left associativity (see Section 4.4.2).

Dually, an operator symbol can be converted to an ordinary identifier by enclosing it in parentheses. For example, (+) x y is equivalent to x + y, and foldr (*) 1 xs is equivalent to foldr (\x y -> x*y) xs.

Special syntax is used to name some constructors for some of the built-in types, as found in the production for 𝑔𝑐𝑜𝑛 and 𝑙𝑖𝑡𝑒𝑟𝑎𝑙. These are described in Section 6.1.

An integer literal represents the application of the function fromInteger to the appropriate value of type Integer. Similarly, a floating point literal stands for an application of fromRational to a value of type Rational (that is, Ratio Integer).

Translation: The integer literal 𝑖 is equivalent to 𝚏𝚛𝚘𝚖𝙸𝚗𝚝𝚎𝚐𝚎𝚛𝑖, where fromInteger is a method in class Num (see Section 6.4.1).

The floating point literal 𝑓 is equivalent to 𝚏𝚛𝚘𝚖𝚁𝚊𝚝𝚒𝚘𝚗𝚊𝚕(𝑛𝚁𝚊𝚝𝚒𝚘.%𝑑), where fromRational is a method in class Fractional and Ratio.% constructs a rational from two integers, as defined in the module Data.Ratio from the standard library. The integers 𝑛 and 𝑑 are chosen so that 𝑛/𝑑=𝑓.

3.3 Curried Applications and Lambda Abstractions

𝑓𝑒𝑥𝑝[𝑓𝑒𝑥𝑝]𝑎𝑒𝑥𝑝(function application)
𝑙𝑒𝑥𝑝\𝑎𝑝𝑎𝑡1𝑎𝑝𝑎𝑡𝑛->𝑒𝑥𝑝(lambda abstraction 𝑛1)

Function application is written 𝑒1𝑒2. Application associates to the left, so the parentheses may be omitted in (f x) y. Because 𝑒1 could be a data constructor, partial applications of data constructors are allowed.

Lambda abstractions are written \𝑝1𝑝𝑛->𝑒, where the 𝑝𝑖 are patterns. An expression such as \x:xs->x is syntactically incorrect; it may legally be written as \(x:xs)->x.

The set of patterns must be linear—no variable may appear more than once in the set.

Translation: The following identity holds:

\𝑝1𝑝𝑛->𝑒=\𝑥1𝑥𝑛->𝚌𝚊𝚜𝚎(𝑥1,,𝑥𝑛)𝚘𝚏(𝑝1,,𝑝𝑛)->𝑒

where the 𝑥𝑖 are new identifiers.

Given this translation combined with the semantics of case expressions and pattern matching described in Section 3.17.3, if the pattern fails to match, then the result is .

3.4 Operator Applications

𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝𝑙𝑒𝑥𝑝𝑞𝑜𝑝𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝
|-𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝(prefix negation)
|𝑙𝑒𝑥𝑝
𝑞𝑜𝑝𝑞𝑣𝑎𝑟𝑜𝑝|𝑞𝑐𝑜𝑛𝑜𝑝(qualified operator)

The form 𝑒1𝑞𝑜𝑝𝑒2 is the infix application of binary operator 𝑞𝑜𝑝 to expressions 𝑒1 and 𝑒2.

The special form 𝑒 denotes prefix negation, the only prefix operator in Haskell, and is syntax for 𝚗𝚎𝚐𝚊𝚝𝚎(𝑒). The binary - operator does not necessarily refer to the definition of - in the Prelude; it may be rebound by the module system. However, unary - will always refer to the negate function defined in the Prelude. There is no link between the local meaning of the - operator and unary negation.

Prefix negation has the same precedence as the infix operator - defined in the Prelude (see Table 1). Because e1-e2 parses as an infix application of the binary operator -, one must write e1(-e2) for the alternative parsing. Similarly, (-) is syntax for \x y -> x-y, as with any infix operator, and does not denote \x -> -x—one must use negate for that.

Translation: The following identities hold:

𝑒1𝑜𝑝𝑒2=(𝑜𝑝)𝑒1𝑒2𝑒=𝚗𝚎𝚐𝚊𝚝𝚎(𝑒)

3.5 Sections

𝑎𝑒𝑥𝑝(𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝𝑞𝑜𝑝)(left section)
|(𝑞𝑜𝑝-𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝)(right section)

Sections are written as (𝑜𝑝𝑒) or (𝑒𝑜𝑝), where 𝑜𝑝 is a binary operator and 𝑒 is an expression. Sections are a convenient syntax for partial application of binary operators.

Syntactic precedence rules apply to sections as follows. (𝑜𝑝𝑒) is legal if and only if (𝑥𝑜𝑝𝑒) parses in the same way as (𝑥𝑜𝑝(𝑒)); and similarly for (𝑒𝑜𝑝. For example, (*a+b) is syntactically invalid, but (+a*b) and (*(a+b)) are valid. Because (+) is left associative, (a+b+) is syntactically correct, but (+a+b) is not; the latter may legally be written as (+(a+b)). As another example, the expression

  (let n = 10 in n +)

is invalid because, by the let/lambda meta-rule (Section 3), the expression

  (let n = 10 in n + x)

parses as

  (let n = 10 in (n + x))

rather than

  ((let n = 10 in n) + x)

Because - is treated specially in the grammar, (𝑒𝑥𝑝) is not a section, but an application of prefix negation, as described in the preceding section. However, there is a subtract function defined in the Prelude such that (𝚜𝚞𝚋𝚝𝚛𝚊𝚌𝚝𝑒𝑥𝑝) is equivalent to the disallowed section. The expression (+(𝑒𝑥𝑝)) can serve the same purpose.

Translation: The following identities hold:

(𝑜𝑝𝑒)=\𝑥->𝑥𝑜𝑝𝑒(𝑒𝑜𝑝)=\𝑥->𝑒𝑜𝑝𝑥

where 𝑜𝑝 is a binary operator, 𝑒 is an expression, and 𝑥 is a variable that does not occur free in 𝑒.

3.6 Conditionals

𝑙𝑒𝑥𝑝𝚒𝚏𝑒𝑥𝑝[;]𝚝𝚑𝚎𝚗𝑒𝑥𝑝[;]𝚎𝚕𝚜𝚎𝑒𝑥𝑝

A conditional expression has the form 𝚒𝚏𝑒1𝚝𝚑𝚎𝚗𝑒2𝚎𝚕𝚜𝚎𝑒3 and returns the value of 𝑒2 if the value of 𝑒1 is True, 𝑒3 if 𝑒1 is False, and otherwise.

Translation: The following identity holds:

𝚒𝚏𝑒1𝚝𝚑𝚎𝚗𝑒2𝚎𝚕𝚜𝚎𝑒3=𝚌𝚊𝚜𝚎𝑒1𝚘𝚏{𝚃𝚛𝚞𝚎->𝑒2;𝙵𝚊𝚕𝚜𝚎->𝑒3}

where True and False are the two nullary constructors from the type Bool, as defined in the Prelude. The type of 𝑒1 must be Bool; 𝑒2 and 𝑒3 must have the same type, which is also the type of the entire conditional expression.

3.7 Lists

𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝𝑒𝑥𝑝1𝑞𝑜𝑝𝑒𝑥𝑝2
𝑎𝑒𝑥𝑝[𝑒𝑥𝑝1,,𝑒𝑥𝑝𝑘](𝑘1)
|𝑔𝑐𝑜𝑛
𝑔𝑐𝑜𝑛[]
|𝑞𝑐𝑜𝑛
𝑞𝑐𝑜𝑛(𝑔𝑐𝑜𝑛𝑠𝑦𝑚)
𝑞𝑜𝑝𝑞𝑐𝑜𝑛𝑜𝑝
𝑞𝑐𝑜𝑛𝑜𝑝𝑔𝑐𝑜𝑛𝑠𝑦𝑚
𝑔𝑐𝑜𝑛𝑠𝑦𝑚:

Lists are written [𝑒1,,𝑒𝑘], where 𝑘1. The list constructor is :, and the empty list is denoted []. Standard operations on lists are given in the Prelude (see Section 6.1.3, and Chapter 9 notably Section 9.1).

Translation: The following identity holds:

[𝑒1,,𝑒𝑘]=𝑒1:(𝑒2:((𝑒𝑘:[])))

where : and [] are constructors for lists, as defined in the Prelude (see Section 6.1.3). The types of 𝑒1 through 𝑒𝑘 must all be the same (call it 𝑡), and the type of the overall expression is [t] (see Section 4.1.2).

The constructor “:” is reserved solely for list construction; like [], it is considered part of the language syntax, and cannot be hidden or redefined. It is a right-associative operator, with precedence level 5 (Section 4.4.2).

3.8 Tuples

𝑎𝑒𝑥𝑝(𝑒𝑥𝑝1,,𝑒𝑥𝑝𝑘)(𝑘2)
|𝑞𝑐𝑜𝑛
𝑞𝑐𝑜𝑛(,{,})

Tuples are written (𝑒1,,𝑒𝑘), and may be of arbitrary length 𝑘2. The constructor for an 𝑛-tuple is denoted by (,,), where there are 𝑛1 commas. Thus (a,b,c) and (,,) a b c denote the same value. Standard operations on tuples are given in the Prelude (see Section 6.1.4 and Chapter 9).

Translation: (𝑒1,,𝑒𝑘) for 𝑘2 is an instance of a 𝑘-tuple as defined in the Prelude, and requires no translation. If 𝑡1 through 𝑡𝑘 are the types of 𝑒1 through 𝑒𝑘, respectively, then the type of the resulting tuple is (𝑡1,,𝑡𝑘) (see Section 4.1.2).

3.9 Unit Expressions and Parenthesized Expressions

𝑎𝑒𝑥𝑝𝑔𝑐𝑜𝑛
|(𝑒𝑥𝑝)
𝑔𝑐𝑜𝑛()

The form (𝑒) is simply a parenthesized expression, and is equivalent to 𝑒. The unit expression () has type () (see Section 4.1.2). It is the only member of that type apart from , and can be thought of as the “nullary tuple” (see Section 6.1.5).

Translation: (𝑒) is equivalent to 𝑒.

3.10 Arithmetic Sequences

𝑎𝑒𝑥𝑝[𝑒𝑥𝑝1[,𝑒𝑥𝑝2]..[𝑒𝑥𝑝3]]

The arithmetic sequence [𝑒1,𝑒2..𝑒3] denotes a list of values of type 𝑡, where each of the 𝑒𝑖 has type 𝑡, and 𝑡 is an instance of class Enum.

Translation: Arithmetic sequences satisfy these identities:

[ 𝑒1 ..]=enumFrom 𝑒1
[ 𝑒1, 𝑒2 ..]=enumFromThen 𝑒1 𝑒2
[ 𝑒1 .. 𝑒2 ]=enumFromTo 𝑒1 𝑒2
[ 𝑒1, 𝑒2 .. 𝑒3 ]=enumFromThenTo 𝑒1 𝑒2 𝑒3

where enumFrom, enumFromThen, enumFromTo, and enumFromThenTo are class methods in the class Enum as defined in the Prelude (see Figure 3).

The semantics of arithmetic sequences therefore depends entirely on the instance declaration for the type t. See Section 6.3.4 for more details of which Prelude types are in Enum and their semantics.

3.11 List Comprehensions

𝑎𝑒𝑥𝑝[𝑒𝑥𝑝|𝑞𝑢𝑎𝑙1,,𝑞𝑢𝑎𝑙𝑛](list comprehension, 𝑛1)
𝑞𝑢𝑎𝑙𝑝𝑎𝑡<-𝑒𝑥𝑝(generator)
|𝚕𝚎𝚝𝑑𝑒𝑐𝑙𝑠(local declaration)
|𝑒𝑥𝑝(boolean guard)

A list comprehension has the form [𝑒|𝑞1,,𝑞𝑛], 𝑛1, where the 𝑞𝑖 qualifiers are either

Such a list comprehension returns the list of elements produced by evaluating 𝑒 in the successive environments created by the nested, depth-first evaluation of the generators in the qualifier list. Binding of variables occurs according to the normal pattern matching rules (see Section 3.17), and if a match fails then that element of the list is simply skipped over. Thus:

[ x |  xs   <- [ [(1,2),(3,4)], [(5,4),(3,2)] ],
      (3,x) <- xs ]

yields the list [4,2]. If a qualifier is a boolean guard, it must evaluate to True for the previous pattern match to succeed. As usual, bindings in list comprehensions can shadow those in outer scopes; for example:

[𝑥|𝑥<-𝑥,𝑥<-𝑥]=[𝑧|𝑦<-𝑥,𝑧<-𝑦]

Translation: List comprehensions satisfy these identities, which may be used as a translation into the kernel:

[𝑒|𝚃𝚛𝚞𝚎]=[𝑒]
[𝑒|𝑞]=[𝑒|𝑞,𝚃𝚛𝚞𝚎]
[𝑒|𝑏,𝑄]=𝚒𝚏𝑏𝚝𝚑𝚎𝚗[𝑒,𝑄]𝚎𝚕𝚜𝚎[]
[𝑒|𝑝<-𝑙,𝑄]=𝚕𝚎𝚝 𝚘𝚔=[𝑒|𝑄]
𝚘𝚔_=[]
𝚒𝚗 𝚌𝚘𝚗𝚌𝚊𝚝𝙼𝚊𝚙 𝚘𝚔𝑙
[𝑒|𝚕𝚎𝚝𝑑𝑒𝑐𝑙𝑠,𝑄]=𝚕𝚎𝚝𝑑𝑒𝑐𝑙𝑠𝚒𝚗[𝑒|𝑄]

where 𝑒 ranges over expressions, 𝑝 over patterns, 𝑙 over list-valued expressions, 𝑏 over boolean expressions, 𝑑𝑒𝑐𝑙𝑠 over declaration lists, 𝑞 over qualifiers, and 𝑄 over sequences of qualifiers. ok is a fresh variable. The function concatMap, and boolean value True, are defined in the Prelude.

As indicated by the translation of list comprehensions, variables bound by let have fully polymorphic types while those defined by <- are lambda bound and are thus monomorphic (see Section 4.5.4).

3.12 Let Expressions

𝑙𝑒𝑥𝑝𝚕𝚎𝚝𝑑𝑒𝑐𝑙𝑠𝚒𝚗𝑒𝑥𝑝

Let expressions have the general form 𝚕𝚎𝚝{𝑑1;;𝑑𝑛}𝚒𝚗𝑒, and introduce a nested, lexically-scoped, mutually-recursive list of declarations (let is often called letrec). The scope of the declarations is the expression 𝑒 and the right hand side of the declarations. Declarations are described in Chapter 4. Pattern bindings are matched lazily; an implicit ~ makes these patterns irrefutable. For example,

𝚕𝚎𝚝(𝑥,𝑦)=𝚞𝚗𝚍𝚎𝚏𝚒𝚗𝚎𝚍 𝚒𝚗𝑒

does not cause an execution-time error until x or y is evaluated.

Translation: The dynamic semantics of the expression 𝚕𝚎𝚝{𝑑1;;𝑑𝑛}𝚒𝚗𝑒0 are captured by this translation: After removing all type signatures, each declaration 𝑑𝑖 is translated into an equation of the form 𝑝𝑖=𝑒𝑖, where 𝑝𝑖 and 𝑒𝑖 are patterns and expressions respectively, using the translation in Section 4.4.3. Once done, these identities hold, which may be used as a translation into the kernel:

𝚕𝚎𝚝{𝑝1=𝑒1;;𝑝𝑛=𝑒𝑛}𝚒𝚗𝑒0=𝚕𝚎𝚝(𝑝1,,𝑝𝑛)=(𝑒1,,𝑒𝑛)𝚒𝚗𝑒0
𝚕𝚎𝚝𝑝=𝑒1𝚒𝚗𝑒0=𝚌𝚊𝚜𝚎𝑒1𝚘𝚏𝑝->𝑒0
where no variable in 𝑝 appears free in 𝑒1
𝚕𝚎𝚝𝑝=𝑒1𝚒𝚗𝑒0=𝚕𝚎𝚝𝑝=𝚏𝚒𝚡(\𝑝->𝑒1)𝚒𝚗𝑒0

where fix is the least fixpoint operator. Note the use of the irrefutable patterns ~p. This translation does not preserve the static semantics because the use of case precludes a fully polymorphic typing of the bound variables. The static semantics of the bindings in a let expression are described in Section 4.4.3.

3.13 Case Expressions

𝑙𝑒𝑥𝑝𝚌𝚊𝚜𝚎𝑒𝑥𝑝𝚘𝚏 {𝑎𝑙𝑡𝑠}
𝑎𝑙𝑡𝑠𝑎𝑙𝑡1;;𝑎𝑙𝑡𝑛(𝑛1)
𝑎𝑙𝑡𝑝𝑎𝑡->𝑒𝑥𝑝[𝚠𝚑𝚎𝚛𝚎𝑑𝑒𝑐𝑙𝑠]
|𝑝𝑎𝑡𝑔𝑑𝑝𝑎𝑡[𝚠𝚑𝚎𝚛𝚎𝑑𝑒𝑐𝑙𝑠]
|(empty alternative)
𝑔𝑑𝑝𝑎𝑡𝑔𝑢𝑎𝑟𝑑𝑠->𝑒𝑥𝑝[𝑔𝑑𝑝𝑎𝑡]
𝑔𝑢𝑎𝑟𝑑𝑠|𝑔𝑢𝑎𝑟𝑑1,,𝑔𝑢𝑎𝑟𝑑𝑛(𝑛1)
𝑔𝑢𝑎𝑟𝑑𝑝𝑎𝑡<-𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝(pattern guard)
|𝚕𝚎𝚝𝑑𝑒𝑐𝑙𝑠(local declaration)
|𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝(boolean guard)

A case expression has the general form

𝚌𝚊𝚜𝚎𝑒𝚘𝚏{𝑝1𝑚𝑎𝑡𝑐ℎ1;;𝑝𝑛𝑚𝑎𝑡𝑐ℎ𝑛}

where each 𝑚𝑎𝑡𝑐ℎ𝑖 is of the general form

|𝑔𝑠𝑖1->𝑒𝑖1|𝑔𝑠𝑖𝑚𝑖->𝑒𝑖𝑚𝑖𝚠𝚑𝚎𝚛𝚎𝑑𝑒𝑐𝑙𝑠𝑖

(Notice that in the syntax rule for 𝑔𝑢𝑎𝑟𝑑𝑠, the “|” is a terminal symbol, not the syntactic metasymbol for alternation.) Each alternative 𝑝𝑖𝑚𝑎𝑡𝑐ℎ𝑖 consists of a pattern 𝑝𝑖 and its matches, 𝑚𝑎𝑡𝑐ℎ𝑖. Each match in turn consists of a sequence of pairs of guards 𝑔𝑠𝑖𝑗 and bodies 𝑒𝑖𝑗 (expressions), followed by optional bindings (𝑑𝑒𝑐𝑙𝑠𝑖) that scope over all of the guards and expressions of the alternative.

A guard has one of the following forms:

An alternative of the form

𝑝𝑎𝑡->𝑒𝑥𝑝𝚠𝚑𝚎𝚛𝚎𝑑𝑒𝑐𝑙𝑠

is treated as shorthand for:

𝑝𝑎𝑡|𝚃𝚛𝚞𝚎 ->𝑒𝑥𝑝𝚠𝚑𝚎𝚛𝚎𝑑𝑒𝑐𝑙𝑠

A case expression must have at least one alternative and each alternative must have at least one body. Each body must have the same type, and the type of the whole expression is that type.

A case expression is evaluated by pattern matching the expression 𝑒 against the individual alternatives. The alternatives are tried sequentially, from top to bottom. If 𝑒 matches the pattern of an alternative, then the guarded expressions for that alternative are tried sequentially from top to bottom in the environment of the case expression extended first by the bindings created during the matching of the pattern, and then by the 𝑑𝑒𝑐𝑙𝑠𝑖 in the where clause associated with that alternative.

For each guarded expression, the comma-separated guards are tried sequentially from left to right. If all of them succeed, then the corresponding expression is evaluated in the environment extended with the bindings introduced by the guards. That is, the bindings that are introduced by a guard (either by using a let clause or a pattern guard) are in scope in the following guards and the corresponding expression. If any of the guards fail, then this guarded expression fails and the next guarded expression is tried.

If none of the guarded expressions for a given alternative succeed, then matching continues with the next alternative. If no alternative succeeds, then the result is . Pattern matching is described in Section 3.17, with the formal semantics of case expressions in Section 3.17.3.

A note about parsing. The expression

  case x of { (a,_) | let b = not a in b :: Bool -> a }

is tricky to parse correctly. It has a single unambiguous parse, namely

  case x of { (a,_) | (let b = not a in b :: Bool) -> a }

However, the phrase Bool -> a is syntactically valid as a type, and parsers with limited lookahead may incorrectly commit to this choice, and hence reject the program. Programmers are advised, therefore, to avoid guards that end with a type signature — indeed that is why a 𝑔𝑢𝑎𝑟𝑑 contains an 𝑖𝑛𝑓𝑖𝑥𝑒𝑥𝑝 not an 𝑒𝑥𝑝.

3.14 Do Expressions

𝑙𝑒𝑥𝑝𝚍𝚘 {𝑠𝑡𝑚𝑡𝑠}(do expression)
𝑠𝑡𝑚𝑡𝑠𝑠𝑡𝑚𝑡1𝑠𝑡𝑚𝑡𝑛𝑒𝑥𝑝[;](𝑛0)
𝑠𝑡𝑚𝑡𝑒𝑥𝑝;
|𝑝𝑎𝑡<-𝑒𝑥𝑝;
|𝚕𝚎𝚝𝑑𝑒𝑐𝑙𝑠;
|;(empty statement)

A do expression provides a more conventional syntax for monadic programming. It allows an expression such as

  putStr "x: "    >>
  getLine         >>= \l ->
  return (words l)

to be written in a more traditional way as:

  do putStr "x: "
     l <- getLine
     return (words l)

Translation: Do expressions satisfy these identities, which may be used as a translation into the kernel, after eliminating empty 𝑠𝑡𝑚𝑡𝑠:

𝚍𝚘{𝑒}=𝑒
𝚍𝚘{𝑒;𝑠𝑡𝑚𝑡𝑠}=𝑒>>𝚍𝚘{𝑠𝑡𝑚𝑡𝑠}
𝚍𝚘{𝑝<-𝑒;𝑠𝑡𝑚𝑡𝑠}=𝚕𝚎𝚝 𝚘𝚔𝑝=𝚍𝚘{𝑠𝑡𝑚𝑡𝑠}
𝚘𝚔_=𝚏𝚊𝚒𝚕 "..."
𝚒𝚗𝑒>>=𝚘𝚔
𝚍𝚘{𝚕𝚎𝚝𝑑𝑒𝑐𝑙𝑠;𝑠𝑡𝑚𝑡𝑠}=𝚕𝚎𝚝𝑑𝑒𝑐𝑙𝑠𝚒𝚗 𝚍𝚘{𝑠𝑡𝑚𝑡𝑠}

The ellipsis “...” stands for a compiler-generated error message, passed to fail, preferably giving some indication of the location of the pattern-match failure; the functions >>, >>=, and fail are operations in the class Monad, as defined in the Prelude; and ok is a fresh identifier.

As indicated by the translation of do, variables bound by let have fully polymorphic types while those defined by <- are lambda bound and are thus monomorphic.

3.15 Datatypes with Field Labels

A datatype declaration may optionally define field labels (see Section 4.2.1). These field labels can be used to construct, select from, and update fields in a manner that is independent of the overall structure of the datatype.

Different datatypes cannot share common field labels in the same scope. A field label can be used at most once in a constructor. Within a datatype, however, a field label can be used in more than one constructor provided the field has the same typing in all constructors. To illustrate the last point, consider:

  data S = S1 { x :: Int } | S2 { x :: Int }   -- OK
  data T = T1 { y :: Int } | T2 { y :: Bool }  -- BAD

Here S is legal but T is not, because y is given inconsistent typings in the latter.

3.15.1 Field Selection

𝑎𝑒𝑥𝑝𝑞𝑣𝑎𝑟

Field labels are used as selector functions. When used as a variable, a field label serves as a function that extracts the field from an object. Selectors are top level bindings and so they may be shadowed by local variables but cannot conflict with other top level bindings of the same name. This shadowing only affects selector functions; in record construction (Section 3.15.2) and update (Section 3.15.3), field labels cannot be confused with ordinary variables.

Translation: A field label 𝑓 introduces a selector function defined as:

𝑓𝑥=𝚌𝚊𝚜𝚎𝑥𝚘𝚏{𝐶1𝑝11𝑝1𝑘->𝑒1;;𝐶𝑛𝑝𝑛1𝑝𝑛𝑘->𝑒𝑛}

where 𝐶1𝐶𝑛 are all the constructors of the datatype containing a field labeled with 𝑓, 𝑝𝑖𝑗 is 𝑦 when 𝑓 labels the 𝑗th component of 𝐶𝑖 or _ otherwise, and 𝑒𝑖 is 𝑦 when some field in 𝐶𝑖 has a label of 𝑓 or undefined otherwise.

3.15.2 Construction Using Field Labels

𝑎𝑒𝑥𝑝𝑞𝑐𝑜𝑛{𝑓𝑏𝑖𝑛𝑑1,,𝑓𝑏𝑖𝑛𝑑𝑛}(labeled construction, 𝑛0)
𝑓𝑏𝑖𝑛𝑑𝑞𝑣𝑎𝑟=𝑒𝑥𝑝

A constructor with labeled fields may be used to construct a value in which the components are specified by name rather than by position. Unlike the braces used in declaration lists, these are not subject to layout; the { and } characters must be explicit. (This is also true of field updates and field patterns.) Construction using field labels is subject to the following constraints:

The expression F {}, where F is a data constructor, is legal whether or not F was declared with record syntax (provided F has no strict fields — see the fourth bullet above); it denotes 𝐹1𝑛, where 𝑛 is the arity of F.

Translation: In the binding 𝑓=𝑣, the field 𝑓 labels 𝑣.

𝐶{𝑏𝑠}=𝐶(𝑝𝑖𝑐𝑘1𝐶𝑏𝑠𝚞𝚗𝚍𝚎𝚏𝚒𝚗𝚎𝚍)(𝑝𝑖𝑐𝑘𝑘𝐶𝑏𝑠𝚞𝚗𝚍𝚎𝚏𝚒𝚗𝚎𝚍)

where 𝑘 is the arity of 𝐶.

The auxiliary function 𝑝𝑖𝑐𝑘𝑖𝐶𝑏𝑠𝑑 is defined as follows:

If the 𝑖th component of a constructor 𝐶 has the field label 𝑓, and if 𝑓=𝑣 appears in the binding list 𝑏𝑠 , then 𝑝𝑖𝑐𝑘𝑖𝐶𝑏𝑠𝑑 is 𝑣. Otherwise, 𝑝𝑖𝑐𝑘𝑖𝐶𝑏𝑠𝑑 is the default value 𝑑.

3.15.3 Updates Using Field Labels

𝑎𝑒𝑥𝑝𝑎𝑒𝑥𝑝𝑞𝑐𝑜𝑛{𝑓𝑏𝑖𝑛𝑑1,,𝑓𝑏𝑖𝑛𝑑𝑛}(labeled update, 𝑛1)

Values belonging to a datatype with field labels may be non-destructively updated. This creates a new value in which the specified field values replace those in the existing value. Updates are restricted in the following ways:

Translation: Using the prior definition of 𝑝𝑖𝑐𝑘,

𝑒{𝑏𝑠}=𝚌𝚊𝚜𝚎𝑒𝚘𝚏
𝐶1𝑣1𝑣𝑘1->𝐶1(𝑝𝑖𝑐𝑘1𝐶1𝑏𝑠𝑣1)(𝑝𝑖𝑐𝑘𝑘1𝐶1𝑏𝑠𝑣𝑘1)
𝐶𝑗𝑣1𝑣𝑘𝑗->𝐶𝑗(𝑝𝑖𝑐𝑘1𝐶𝑗𝑏𝑠𝑣1)(𝑝𝑖𝑐𝑘𝑘𝑗𝐶𝑗𝑏𝑠𝑣𝑘𝑗)
_ -> 𝚎𝚛𝚛𝚘𝚛 "𝚄𝚙𝚍𝚊𝚝𝚎 𝚎𝚛𝚛𝚘𝚛"

where {𝐶1,,𝐶𝑗} is the set of constructors containing all labels in 𝑏𝑠, and 𝑘𝑖 is the arity of 𝐶𝑖.

Here are some examples using labeled fields:

data T    = C1 {f1,f2 :: Int}
          | C2 {f1 :: Int,
                f3,f4 :: Char}
ExpressionTranslation
C1 {f1 = 3}C1 3 undefined
C2 {f1 = 1, f4 = 'A', f3 = 'B'}C2 1 'B' 'A'
x {f1 = 1}case x of C1 _ f2 -> C1 1 f2
C2 _ f3 f4 -> C2 1 f3 f4

The field f1 is common to both constructors in T. This example translates expressions using constructors in field-label notation into equivalent expressions using the same constructors without field labels. A compile-time error will result if no single constructor defines the set of field labels used in an update, such as x {f2 = 1, f3 = 'x'}.

3.16 Expression Type-Signatures

Expression type-signatures have the form 𝑒::𝑡, where 𝑒 is an expression and 𝑡 is a type (Section 4.1.2); they are used to type an expression explicitly and may be used to resolve ambiguous typings due to overloading (see Section 4.3.4). The value of the expression is just that of 𝑒𝑥𝑝. As with normal type signatures (see Section 4.4.1), the declared type may be more specific than the principal type derivable from 𝑒𝑥𝑝, but it is an error to give a type that is more general than, or not comparable to, the principal type.

Translation:

𝑒::𝑡=𝚕𝚎𝚝{𝑣::𝑡;𝑣=𝑒}𝚒𝚗𝑣

3.17 Pattern Matching

Patterns appear in lambda abstractions, function definitions, pattern bindings, list comprehensions, do expressions, and case expressions. However, the first five of these ultimately translate into case expressions, so defining the semantics of pattern matching for case expressions is sufficient.

3.17.1 Patterns

Patterns have this syntax:

𝑝𝑎𝑡𝑙𝑝𝑎𝑡𝑞𝑐𝑜𝑛𝑜𝑝𝑝𝑎𝑡(infix constructor)
|𝑙𝑝𝑎𝑡
𝑙𝑝𝑎𝑡𝑎𝑝𝑎𝑡
|-(𝑖𝑛𝑡𝑒𝑔𝑒𝑟|𝑓𝑙𝑜𝑎𝑡)(negative literal)
|𝑔𝑐𝑜𝑛𝑎𝑝𝑎𝑡1𝑎𝑝𝑎𝑡𝑘(arity 𝑔𝑐𝑜𝑛=𝑘, 𝑘1)
𝑎𝑝𝑎𝑡𝑣𝑎𝑟[@𝑎𝑝𝑎𝑡](as pattern)
|𝑔𝑐𝑜𝑛(arity 𝑔𝑐𝑜𝑛=0)
|𝑞𝑐𝑜𝑛{𝑓𝑝𝑎𝑡1,,𝑓𝑝𝑎𝑡𝑘}(labeled pattern, 𝑘0)
|𝑙𝑖𝑡𝑒𝑟𝑎𝑙
|_(wildcard)
|(𝑝𝑎𝑡)(parenthesized pattern)
|(𝑝𝑎𝑡1,,𝑝𝑎𝑡)(tuple pattern, 𝑘2)
|[𝑝𝑎𝑡1,,𝑝𝑎𝑡](list pattern, 𝑘1)
|~𝑎𝑝𝑎𝑡(irrefutable pattern)
𝑓𝑝𝑎𝑡𝑞𝑣𝑎𝑟=𝑝𝑎𝑡

All patterns must be linear—no variable may appear more than once. For example, this definition is illegal:

f (x,x) = x     -- ILLEGAL; x used twice in pattern

Patterns of the form 𝑣𝑎𝑟@𝑝𝑎𝑡 are called as-patterns, and allow one to use 𝑣𝑎𝑟 as a name for the value being matched by 𝑝𝑎𝑡. For example,

case e of { xs@(x:rest) -> if x==0 then rest else xs }

is equivalent to:

let { xs = e } in
  case xs of { (x:rest) -> if x==0 then rest else xs }

Patterns of the form _ are wildcards and are useful when some part of a pattern is not referenced on the right-hand-side. It is as if an identifier not used elsewhere were put in its place. For example,

case e of { [x,_,_]  ->  if x==0 then True else False }

is equivalent to:

case e of { [x,y,z]  ->  if x==0 then True else False }

3.17.2 Informal Semantics of Pattern Matching

Patterns are matched against values. Attempting to match a pattern can have one of three results: it may fail; it may succeed, returning a binding for each variable in the pattern; or it may diverge (i.e. return ). Pattern matching proceeds from left to right, and outside to inside, according to the following rules:

  1. Matching the pattern 𝑣𝑎𝑟 against a value 𝑣 always succeeds and binds 𝑣𝑎𝑟 to 𝑣.
  2. Matching the pattern 𝑎𝑝𝑎𝑡 against a value 𝑣 always succeeds. The free variables in 𝑎𝑝𝑎𝑡 are bound to the appropriate values if matching 𝑎𝑝𝑎𝑡 against 𝑣 would otherwise succeed, and to if matching 𝑎𝑝𝑎𝑡 against 𝑣 fails or diverges. (Binding does not imply evaluation.)

    Operationally, this means that no matching is done on a 𝑎𝑝𝑎𝑡 pattern until one of the variables in 𝑎𝑝𝑎𝑡 is used. At that point the entire pattern is matched against the value, and if the match fails or diverges, so does the overall computation.

  3. Matching the wildcard pattern _ against any value always succeeds, and no binding is done.
  4. Matching the pattern 𝑐𝑜𝑛𝑝𝑎𝑡 against a value, where 𝑐𝑜𝑛 is a constructor defined by newtype, depends on the value:

    • If the value is of the form 𝑐𝑜𝑛𝑣, then 𝑝𝑎𝑡 is matched against 𝑣.
    • If the value is , then 𝑝𝑎𝑡 is matched against .

    That is, constructors associated with newtype serve only to change the type of a value.

  5. Matching the pattern 𝑐𝑜𝑛𝑝𝑎𝑡1𝑝𝑎𝑡𝑛 against a value, where 𝑐𝑜𝑛 is a constructor defined by data, depends on the value:

    • If the value is of the form 𝑐𝑜𝑛𝑣1𝑣𝑛, sub-patterns are matched left-to-right against the components of the data value; if all matches succeed, the overall match succeeds; the first to fail or diverge causes the overall match to fail or diverge, respectively.
    • If the value is of the form 𝑐𝑜𝑛𝑣1𝑣𝑚, where 𝑐𝑜𝑛 is a different constructor to 𝑐𝑜𝑛, the match fails.
    • If the value is , the match diverges.
  6. Matching against a constructor using labeled fields is the same as matching ordinary constructor patterns except that the fields are matched in the order they are named in the field list. All fields listed must be declared by the constructor; fields may not be named more than once. Fields not named by the pattern are ignored (matched against _).
  7. Matching a numeric, character, or string literal pattern 𝑘 against a value 𝑣 succeeds if 𝑣==𝑘, where == is overloaded based on the type of the pattern. The match diverges if this test diverges.

    The interpretation of numeric literals is exactly as described in Section 3.2; that is, the overloaded function fromInteger or fromRational is applied to an Integer or Rational literal (resp) to convert it to the appropriate type.

  8. Matching an as-pattern 𝑣𝑎𝑟@𝑎𝑝𝑎𝑡 against a value 𝑣 is the result of matching 𝑎𝑝𝑎𝑡 against 𝑣, augmented with the binding of 𝑣𝑎𝑟 to 𝑣. If the match of 𝑎𝑝𝑎𝑡 against 𝑣 fails or diverges, then so does the overall match.

Aside from the obvious static type constraints (for example, it is a static error to match a character against a boolean), the following static class constraints hold:

It is sometimes helpful to distinguish two kinds of patterns. Matching an irrefutable pattern is non-strict: the pattern matches even if the value to be matched is . Matching a refutable pattern is strict: if the value to be matched is the match diverges. The irrefutable patterns are as follows: a variable, a wildcard, 𝑁𝑎𝑝𝑎𝑡 where 𝑁 is a constructor defined by newtype and 𝑎𝑝𝑎𝑡 is irrefutable (see Section 4.2.3), 𝑣𝑎𝑟@𝑎𝑝𝑎𝑡 where 𝑎𝑝𝑎𝑡 is irrefutable, or of the form 𝑎𝑝𝑎𝑡 (whether or not 𝑎𝑝𝑎𝑡 is irrefutable). All other patterns are refutable.

Here are some examples:

  1. If the pattern ['a','b'] is matched against [𝑥,], then 'a' fails to match against 'x', and the result is a failed match. But if ['a','b'] is matched against [,𝑥], then attempting to match 'a' against causes the match to diverge.

  2. These examples demonstrate refutable vs. irrefutable matching:

    (\ ~(x,y) -> 0) 0
    (\ (x,y) -> 0)
    (\ ~[x] -> 0) []0
    (\ ~[x] -> x) []
    (\ ~[x, ~(a,b)] -> x [(0,1),](0,1)
    (\ ~[x, (a,b)] -> x [(0,1),]
    (\ (x:xs) -> x:x:xs)
    (\ ~(x:xs) -> x:x:xs) ::
  3. Consider the following declarations:

    newtype N = N Bool
    data    D = D !Bool

    These examples illustrate the difference in pattern matching between types defined by data and newtype:

    (\ (N True) -> True)
    (\ (D True) -> True)
    (\ ~(D True) -> True) True

    Additional examples may be found in Section 4.2.3.

Top level patterns in case expressions and the set of top level patterns in function or pattern bindings may have zero or more associated guards. See Section 3.13 for the syntax and semantics of guards.

The guard semantics have an influence on the strictness characteristics of a function or case expression. In particular, an otherwise irrefutable pattern may be evaluated because of a guard. For example, in

f :: (Int,Int,Int) -> [Int] -> Int
f ~(x,y,z) [a] | (a == y) = 1

both a and y will be evaluated by == in the guard.

3.17.3 Formal Semantics of Pattern Matching

The semantics of all pattern matching constructs other than case expressions are defined by giving identities that relate those constructs to case expressions. The semantics of case expressions themselves are in turn given as a series of identities, in Figure 1Figure 2. Any implementation should behave so that these identities hold; it is not expected that it will use them directly, since that would generate rather inefficient code.

In Figure 1Figure 2: 𝑒, 𝑒 and 𝑒𝑖 are expressions; 𝑔𝑖 and 𝑔𝑠𝑖 are guards and sequences of guards respectively; 𝑝 and 𝑝𝑖 are patterns; 𝑣, 𝑥, and 𝑥𝑖 are variables; 𝐾 and 𝐾 are algebraic datatype (data) constructors (including tuple constructors); and 𝑁 is a newtype constructor.

Rule (b) matches a general source-language case expression, regardless of whether it actually includes guards—if no guards are written, then True is substituted for the guards 𝑔𝑠𝑖,𝑗 in the 𝑚𝑎𝑡𝑐ℎ𝑖 forms. Subsequent identities manipulate the resulting case expression into simpler and simpler forms.

Rule (h) in Listing 3 involves the overloaded operator ==; it is this rule that defines the meaning of pattern matching against overloaded constants.

These identities all preserve the static semantics. Rules (d), (e), (j), and (q) use a lambda rather than a let; this indicates that variables bound by case are monomorphically typed (Section 4.1.4).

(a)
𝚌𝚊𝚜𝚎𝑒𝚘𝚏{ 𝑎𝑙𝑡𝑠 }=(\𝑣->𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝑎𝑙𝑡𝑠 }) 𝑒
where 𝑣 is a new variable
(b)

𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝑝1 𝑚𝑎𝑡𝑐ℎ1;;𝑝𝑛 𝑚𝑎𝑡𝑐ℎ𝑛 }
=𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝑝1 𝑚𝑎𝑡𝑐ℎ1;
_ ->𝚌𝚊𝚜𝚎𝑣𝚘𝚏{
𝑝𝑛 𝑚𝑎𝑡𝑐ℎ𝑛;
_ -> 𝚎𝚛𝚛𝚘𝚛 "𝙽𝚘 𝚖𝚊𝚝𝚌𝚑"}}
where each 𝑚𝑎𝑡𝑐ℎ𝑖 has the form

|𝑔𝑠𝑖,1->𝑒𝑖,1;;𝑔𝑠𝑖,𝑚𝑖->𝑒𝑖,𝑚𝑖𝚠𝚑𝚎𝚛𝚎{𝑑𝑒𝑐𝑙𝑠}
(c)
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝑝|𝑔𝑠1->𝑒1;
|𝑔𝑠𝑛->𝑒𝑛𝚠𝚑𝚎𝚛𝚎{𝑑𝑒𝑐𝑙𝑠}
_ ->𝑒 }
=𝚌𝚊𝚜𝚎𝑒𝚘𝚏{ 𝑦->
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{
𝑝->𝚕𝚎𝚝{𝑑𝑒𝑐𝑙𝑠}𝚒𝚗
𝚌𝚊𝚜𝚎()𝚘𝚏{
()|𝑔𝑠1->𝑒1;
_ -> 𝚌𝚊𝚜𝚎()𝚘𝚏{
()|𝑔𝑠𝑛->𝑒𝑛;
_ ->𝑦 } }
_ ->𝑦 }}
where 𝑦 is a new variable
(d)
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{~𝑝->𝑒; _ -> 𝑒}
=(\𝑥1𝑥𝑛->𝑒)(𝚌𝚊𝚜𝚎𝑣𝚘𝚏{𝑝->𝑥1})(𝚌𝚊𝚜𝚎𝑣𝚘𝚏{𝑝->𝑥𝑛})
where 𝑥1,,𝑥𝑛 are all the variables in 𝑝
(e)
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝑥@𝑝->𝑒 ; _ ->𝑒}
=𝚌𝚊𝚜𝚎𝑣𝚘𝚏{𝑝->(\𝑥->𝑒) 𝑣 ; _ ->𝑒}
(f)
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ _ ->𝑒 ; _ ->𝑒 }=𝑒
Figure 1: Semantics of Case Expressions, Part 1
(g)
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝐾𝑝1𝑝𝑛->𝑒_ ->𝑒 }
=𝚌𝚊𝚜𝚎𝑣𝚘𝚏{
𝐾 𝑥1𝑥𝑛->𝚌𝚊𝚜𝚎𝑥1𝚘𝚏{
𝑝1->𝚌𝚊𝚜𝚎𝑥𝑛𝚘𝚏{𝑝𝑛->𝑒; _ ->𝑒}
_ ->𝑒}
_ ->𝑒}
at least one of 𝑝1,,𝑝𝑛 is not a variable; 𝑥1,,𝑥𝑛 are new variables
(h)
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝑘->𝑒; _ ->𝑒 }=𝚒𝚏(𝑣==𝑘)𝚝𝚑𝚎𝚗𝑒𝚎𝚕𝚜𝚎𝑒
where 𝑘 is a numeric, character, or string literal
(i)
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝑥->𝑒; _ ->𝑒 }=𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝑥->𝑒 }
(j)
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝑥->𝑒 }=(\𝑥->𝑒) 𝑣
(k)
𝚌𝚊𝚜𝚎𝑁𝑣𝚘𝚏{ 𝑁𝑝->𝑒; _ ->𝑒 }
=𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝑝->𝑒; _ ->𝑒 }
where 𝑁 is a newtype constructor
(l)
𝚌𝚊𝚜𝚎𝚘𝚏{ 𝑁 𝑝->𝑒; _ ->𝑒 }=𝚌𝚊𝚜𝚎𝚘𝚏{ 𝑝-> 𝑒 }
where 𝑁 is a newtype constructor
(m)
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝐾{𝑓1=𝑝1,𝑓2=𝑝2,}->𝑒; _ ->𝑒 }
=𝚌𝚊𝚜𝚎𝑒𝚘𝚏{
𝑦->
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{
𝐾{𝑓1=𝑝1}->
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{𝐾{𝑓2=𝑝2,}->𝑒; _ ->𝑦};
_ ->𝑦}}
where 𝑓1,𝑓2, are fields of constructor 𝐾; 𝑦 is a new variable
(n)
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝐾{𝑓=𝑝}->𝑒; _ ->𝑒 }
=𝚌𝚊𝚜𝚎𝑣𝚘𝚏{
𝐾𝑝1𝑝𝑛->𝑒; _ ->𝑒}
where 𝑝𝑖 is 𝑝 if 𝑓 labels the 𝑖th component of 𝐾, _ otherwise
(o)
𝚌𝚊𝚜𝚎𝑣𝚘𝚏{ 𝐾 { }->𝑒; _ ->𝑒 }
=𝚌𝚊𝚜𝚎𝑣𝚘𝚏{
𝐾__->𝑒; _ ->𝑒}
(p)
𝚌𝚊𝚜𝚎(𝐾 𝑒1𝑒𝑚)𝚘𝚏{ 𝐾 𝑥1𝑥𝑛->𝑒; _ ->𝑒 }=𝑒
where 𝐾 and 𝐾 are distinct data constructors of arity 𝑛 and 𝑚, respectively
(q)
𝚌𝚊𝚜𝚎(𝐾𝑒1𝑒𝑛)𝚘𝚏{ 𝐾𝑥1𝑥𝑛->𝑒; _ ->𝑒 }
=(\𝑥1𝑥𝑛->𝑒)𝑒1𝑒𝑛
where 𝐾 is a data constructor of arity 𝑛
(r)
𝚌𝚊𝚜𝚎𝚘𝚏{ 𝐾𝑥1𝑥𝑛->𝑒; _ ->𝑒 }=
where 𝐾 is a data constructor of arity 𝑛
Listing 3: Semantics of Case Expressions, Part 2
(s)
𝚌𝚊𝚜𝚎()𝚘𝚏{ ()|𝑔1,,𝑔𝑛->𝑒; _ ->𝑒 }
=𝚌𝚊𝚜𝚎()𝚘𝚏{
()|𝑔1->𝚌𝚊𝚜𝚎()𝚘𝚏{
()|𝑔𝑛->𝑒;
_ ->𝑒 }
_ ->𝑒 }
where 𝑦 is a new variable
(t)
𝚌𝚊𝚜𝚎()𝚘𝚏{ ()|𝑝<-𝑒0->𝑒; _ ->𝑒 }
=𝚌𝚊𝚜𝚎𝑒0𝚘𝚏{ 𝑝->𝑒; _ ->𝑒 }
(u)
𝚌𝚊𝚜𝚎()𝚘𝚏{ ()|𝚕𝚎𝚝𝑑𝑒𝑐𝑙𝑠->𝑒; _ ->𝑒 }
=𝚕𝚎𝚝𝑑𝑒𝑐𝑙𝑠𝚒𝚗𝑒
(v)
𝚌𝚊𝚜𝚎()𝚘𝚏{ ()|𝑒0->𝑒; _ ->𝑒 }
=𝚒𝚏𝑒0𝚝𝚑𝚎𝚗𝑒𝚎𝚕𝚜𝚎𝑒
Figure 2: Semantics of Case Expressions, Part 3