Tuesday, January 29, 2013

HASKELL CONTROL STRUCTURE INTRODUCTION

HASKELL CONTROL STRUCTURE INTRODUCTION


REVISED: Friday, February 9, 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:

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.

In Haskell the else is mandatory.

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

Pattern matching limits us to performing fixed tests of a value's shape. We can use pattern matching to ensure we are looking at values of the right shape. We can use guards to compare pieces of a values shape.

| (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 property 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 in order 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:

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> 

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>

II. CONCLUSION

In this tutorial, you have received an introduction to 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.