REVISED: Saturday, October 19, 2024
Haskell Case Expressions.
I. WRITING HASKELL CASE EXPRESSIONS
A. PATTERN MATCHING
You can use pattern matching on function parameters only when you are defining functions.
Copy the following module example and paste it into your text editor:
module ListCasesPM where
import Data.List
listCasesPM :: [a] -> String
listCasesPM xs = "The list is " ++ what xs
where what [] = "empty."
what [x] = "a singleton list."
what xs = "a longer list."
The example above should be saved as ListCasesPM.hs.
Load the module ListCasesPM as shown below:
Since the function signature for listCasesPM shows a list [a] mapped to a String, we have to use a list of arguments when we call the function in GHCi, as shown below:
case expression of pattern -> result
pattern -> result
pattern -> result
...
"Copy Paste" the following module example and into your text editor:
module ListCasesCE where
import Data.List
listCasesCE :: [a] -> String
listCasesCE xs = "The list is " ++ case xs of [] -> "an empty list."
[x] -> "a singleton list."
xs -> "a longer list."
The example above should be saved as ListCasesCE.hs to your working directory.
Open GHCi and load ListCasesCE as shown below:
Prelude> :load ListCasesCE
[1 of 1] Compiling ListCasesCE ( ListCasesCE.hs, interpreted )
Ok, modules loaded: ListCasesCE.
There is one use of a case expression that is so common that it has special syntax: the conditional expression.
Conditional expressions have the form:
if e1 then e2 else e3
which is really short-hand for:
case e1 of True -> e2
False -> e3
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.
You can put any valid Haskell expression between the keywords case and of.
The case statement will check each alternative, in the order they are listed until it finds a pattern that matches. Once a match is found, the expression on the right hand side of the -> is evaluated. After a match is found, no further alternatives are considered.
The case statement will always evaluate exactly one alternative.
To avoid a compiler "non-exhaustive pattern" warning, you must include a pattern that matches.
To avoid a compiler "overlapping pattern" warning, do not include overlapping alternatives, for example, more than one pattern that matches.
III. CONCLUSION
The case statement will check each alternative; after a match is found, no further alternatives are considered.
Bird, R. (2015). Thinking Functionally with Haskell. Cambridge, England: Cambridge University Press.
Davie, A. (1992). Introduction to Functional Programming Systems Using Haskell. Cambridge, England: Cambridge University Press.
Goerzen, J. & O'Sullivan, B. & Stewart, D. (2008). Real World Haskell. Sebastopol, CA: O'Reilly Media, Inc.
Hutton, G. (2007). Programming in Haskell. New York: Cambridge University Press.
Lipovača, M. (2011). Learn You a Haskell for Great Good!: A Beginner's Guide. San Francisco, CA: No Starch Press, Inc.
Thompson, S. (2011). The Craft of Functional Programming. Edinburgh Gate, Harlow, England: Pearson Education Limited.
You can use pattern matching on function parameters only when you are defining functions.
Copy the following module example and paste it into your text editor:
import Data.List
listCasesPM :: [a] -> String
listCasesPM xs = "The list is " ++ what xs
where what [] = "empty."
what [x] = "a singleton list."
what xs = "a longer list."
The example above should be saved as ListCasesPM.hs.
Load the module ListCasesPM as shown below:
Prelude> :load ListCasesPM
[1 of 1] Compiling ListCasesPM ( ListCasesPM.hs, interpreted )
Ok, modules loaded: ListCasesPM.
Prelude>
Since the function signature for listCasesPM shows a list [a] mapped to a String, we have to use a list of arguments when we call the function in GHCi, as shown below:
Prelude> listCasesPM []
"The list is empty."
Case expressions can be used anywhere.
"The list is empty."
Prelude>
Prelude> listCasesPM ["Hello, World!"]
Prelude> listCasesPM ["Hello, World!"]
"The list is a singleton list."
Prelude>
Prelude> listCasesPM ["Hello, World!","Good-bye, World!"]
Prelude> listCasesPM ["Hello, World!","Good-bye, World!"]
"The list is a longer list."
Prelude>
B. CASE EXPRESSIONS
The syntax for case expressions is as follows:
case expression of pattern -> result
pattern -> result
pattern -> result
...
"Copy Paste" the following module example and into your text editor:
module ListCasesCE where
import Data.List
listCasesCE :: [a] -> String
listCasesCE xs = "The list is " ++ case xs of [] -> "an empty list."
[x] -> "a singleton list."
xs -> "a longer list."
The example above should be saved as ListCasesCE.hs to your working directory.
Open GHCi and load ListCasesCE as shown below:
Prelude> :load ListCasesCE
[1 of 1] Compiling ListCasesCE ( ListCasesCE.hs, interpreted )
Ok, modules loaded: ListCasesCE.
Prelude>
Since the function signature for listCasesCE shows a list [a] mapped to a String, we have to use a list of arguments when we call the function in GHCi, as shown below:
Prelude> listCasesCE []
"The list is empty."
Prelude>
Since the function signature for listCasesCE shows a list [a] mapped to a String, we have to use a list of arguments when we call the function in GHCi, as shown below:
"The list is empty."
Prelude>
Prelude> listCasesCE ["Hello, World!"]
Prelude> listCasesCE ["Hello, World!"]
"The list is a singleton list."
Prelude>
Prelude> listCasesCE ["Hello, World!","Good-bye, World!"]
Prelude> listCasesCE ["Hello, World!","Good-bye, World!"]
"The list is a longer list."
C. CONDITIONAL EXPRESSIONS
There is one use of a case expression that is so common that it has special syntax: the conditional expression.
if e1 then e2 else e3
which is really short-hand for:
case e1 of True -> e2
False -> e3
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.
You can put any valid Haskell expression between the keywords case and of.
The case statement will check each alternative, in the order they are listed until it finds a pattern that matches. Once a match is found, the expression on the right hand side of the -> is evaluated. After a match is found, no further alternatives are considered.
The case statement will always evaluate exactly one alternative.
To avoid a compiler "non-exhaustive pattern" warning, you must include a pattern that matches.
To avoid a compiler "overlapping pattern" warning, do not include overlapping alternatives, for example, more than one pattern that matches.
III. CONCLUSION
The case statement will check each alternative; after a match is found, no further alternatives are considered.
IV. REFERENCES
Bird, R. (2015). Thinking Functionally with Haskell. Cambridge, England: Cambridge University Press.
Davie, A. (1992). Introduction to Functional Programming Systems Using Haskell. Cambridge, England: Cambridge University Press.
Goerzen, J. & O'Sullivan, B. & Stewart, D. (2008). Real World Haskell. Sebastopol, CA: O'Reilly Media, Inc.
Hutton, G. (2007). Programming in Haskell. New York: Cambridge University Press.
Lipovača, M. (2011). Learn You a Haskell for Great Good!: A Beginner's Guide. San Francisco, CA: No Starch Press, Inc.
Thompson, S. (2011). The Craft of Functional Programming. Edinburgh Gate, Harlow, England: Pearson Education Limited.