REVISED: Friday, October 18, 2024
In this tutorial, you will receive an introduction to Haskell control structure.
I. HASKELL CONTROL STRUCTURE
Without mutable variables, recursion is the only way to implement control structures.
A. HASKELL IF EXPRESSION
if condition
then trueValue
else falseValue
An expression is a piece of code that returns a value.
Haskell's "if expression" syntax is as follows:
Haskell's "if expression" syntax is as follows:
if <condition> then <trueValue> else <falseValue>
<condition> is an expression which evaluates to a Boolean. If the <condition> is True then the <trueValue> is returned, otherwise the <falseValue> is returned.
The <trueValue> and <falseValue> must evaluate to the same type, which will be the type of the whole if expression.
Semicolons ; are not allowed in an if/then/else.
then and else must be indented deeper than the if statement.
The expressions after the then and else keywords are branches. The branches must have the same types. if expressions must also have the same types.
B. HASKELL GUARDS
Guards are a conditional expression mechanism in Haskell that allows you to select different expressions based on the truth value of certain conditions. They are often used to define functions with multiple cases or to implement complex logic in a concise and readable way.
| (guard boolean expression) = (guard function body expression)
A pattern can be followed by zero or more guards. Guards must be expressions of type Bool. A guard begins with a | pipe symbol, followed by the Boolean guard expression. Then followed by an = equal symbol, or -> to symbol if we are in a case expression. Then followed by the body to use if the Boolean guard expression evaluates to True. If a pattern matches, each guard associated with that pattern is evaluated, in the order in which the guards are written. If a Boolean guard expression evaluates to True, the body affiliated with that guard is used as the result of the function. If no guard evaluates to True, pattern matching continues to the next pattern.
The -> function arrow, read "to", can take two types; for example, Int and Bool and produce a new type Int -> Bool. The function arrow -> describes a function mapping from one type "to" another.
When a guard expression evaluates to True, all of the variables mentioned in the pattern with which it is associated are bound and can be used.
Guards are a sequence of logical expressions used to choose between a sequence of results of the same type. If the first guard is True then the first result is chosen, otherwise, if the second guard is True then the second result is chosen, and so on.
Guards are a way of testing whether some properties of a value are True or False.
A guard is a Boolean expression. If it evaluates to True, the corresponding function body is used. If it evaluates to False, checking drops through to the next guard; etc.
Always use an otherwise guard as the last guard to have a match for all remaining cases. otherwise is defined as otherwise = True and catches everything you did not code in the other guards.
Guards can be used instead of if-then-else expressions. Guards are evaluated in order and indicate various cases in the computation. The first guard that is True controls the result.
Module:
-- BooleanXY.hs
module BooleanXY where
booleanXY :: (Ord a1, Ord a, Num a1, Num a) => a -> a1 -> [Char]
booleanXY x y
| x < 50 = "No"
| y >= 50 = "Yes"
| otherwise = "Maybe"
GHCi:
Prelude> :load BooleanXY
[1 of 1] Compiling Main ( BooleanXY.hs, interpreted )
Ok, modules loaded: Main.
Prelude>
Prelude> :type booleanXY
booleanXY :: (Ord a1, Ord a, Num a1, Num a) => a -> a1 -> [Char]
Prelude>
Prelude> booleanXY 10 50
"No"
Prelude>
Prelude> booleanXY 50 50
"Yes"
Prelude>
Prelude> booleanXY 60 30
"Maybe"
Prelude>
PS C:\Users\User\tinnel\Haskell 2024\newProjects> ghci
GHCi, version 9.4.8: https://www.haskell.org/ghc/ :? for help
ghci> :load BooleanXY.hs
[1 of 1] Compiling BooleanXY ( BooleanXY.hs, interpreted )
Ok, one module loaded.
ghci> booleanXY 10 50
"No"
ghci> booleanXY 50 50
"Yes"
ghci> booleanXY 60 30
"Maybe"
ghci> :quit
Module:
module MyReplicate where
myReplicate :: (Ord a, Num a) => a -> t -> [t]
myReplicate n x
| n <= 0 = []
| otherwise = x:myReplicate (n-1) x
GHCi:
Prelude> :load MyReplicate
[1 of 1] Compiling MyReplicate ( MyReplicate.hs, interpreted )
Ok, modules loaded: MyReplicate.
Prelude> myReplicate 5 47
[47,47,47,47,47]
Preluce>
Prelude> myReplicate 47 5
[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5]
Prelude>
Prelude> myReplicate (-47) (-5)
[]
Prelude>
PS C:\Users\User\tinnel\Haskell 2024\newProjects> ghci
GHCi, version 9.4.8: https://www.haskell.org/ghc/ :? for help
ghci> :load MyReplicate.hs
[1 of 1] Compiling MyReplicate ( MyReplicate.hs, interpreted )
Ok, one module loaded.
ghci> myReplicate 5 47
[47,47,47,47,47]
ghci> myReplicate 47 5
[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5]
ghci> myReplicate (-47) (-5)
[]
ghci> :quit
Leaving GHCi.
PS C:\Users\User\tinnel\Haskell 2024\newProjects>
II. CONCLUSION
In this tutorial, you have received an introduction to the Haskell control structure.
III. 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.