Control Structures

Haskell is quite a bit different when it comes to control structures for directing the flow of your program.

A statements is block of code which does not return any values after the execution, An Expression is also a block of code but expression returns some value.

To start off with, Haskell has if expressions. This differentiates itself from an if statement. A statement is an action to execute. That’s the smallest standalone line of code in an imperative programming language.

Haskell doesn’t have statements though, only expressions (and declarations). An expression is a piece of code that is evaluated to a value, like a function, which makes sense since Haskell is a functional programming language, composed of many functions.

This means you can assign the simplified expression of control structures in Haskell directly to variables because they act as functions themselves.

test :: Integral a => a -> a
test g = f g
  where f = if even g then (+) 2 else (+) 3

Now that you’ve got it straight between expressions and statements let’s dig into if-then-else blocks.

if-then-else expressions

An if-then-else block structure is this:

if (A conditional expression evaluated to True or False)
then (An expression returned when the condition is True)
else (An expression returned when the condition is False)
  • The expression you put in your if expression must result in either True or False.
  • You gotta have an else to handle a False if value. You must have the else expression. Otherwise you will get a parse error. These are the rules

In the example below, we can see that the variable text will always be equal to "something to work" since the conditional expression True is fully evaluated and remains True.

text = if True then "something to work" else "something's not working"

Here’s an example of a function that takes a variable and the condition changes. If the food variable isn’t "pizza" the else expression is evaluated. Try it out for yourself!

party food = if food == "pizza" then "hooray pizza party!" else "it's not pizza :("

In the below example, the given condition fails. So, the else block will be executed.

main = do
   let var = 23
   if var `rem` 2 == 0
      then putStrLn "Number is Even"
   else putStrLn "Number is Odd"

It will produce the following output

Number is Odd

Case expressions in Haskell

Case expressions are similar to if-then-else expressions. In fact, we can rewrite our last example using a case expression instead.

party' food =
  case food == "pizza" of
    True  -> "hooray pizza party!"
    False -> "it's not pizza :("

The condition you want to evaluate goes in between the case and of and then you can match on the various values that can be returned, in this instance (==) evaluates to True or False.

There are couple of differences you probably see here.

  • We match on the possible values our expression can reduce to.
  • We got these cool arrow guys that point to the expression we want to return based on the matched value or otherwise case.
  • It doesn’t have to be a boolean expression. This opens up a lot of choices for the expression you want to use for a case. Below I did a silly example of “comparing´┐Ż? the variable food to the string "pizza"
compare :: a -> a -> Ordering

The possible values of Ordering are LT | EQ | GT

pizza' food =
  case compare food "pizza" of
    LT -> "This food is weaker than pizza"
    EQ -> "Pizza is the correct party food"
    GT -> "This food is greater than pizza!!!!"

We don’t have to match on the cases with the values specifically. An underscore _ can be used to catch any of the cases we don’t handle specifically.

_ is kinda like a variable (identifier) in Haskell, but you can’t assign it to anything… It says "we don’t care about this value"? This will make sure our case expression is a complete function, handling all the different possibilities.

pizza'' food =
  case compare food "pizza" of
    EQ -> "Pizza is the correct party food"
    _  -> "Why are you bringing anything other than pizza to this party"

Guards in Haskell

Guards have some aspects of case expressions and some aspects of if-then-else. They are similar to case expressions because you can have multiple expressions/values which results in 2 or more possible outcomes.

They are similar to if-then-else expressions because those expressions must evaluate to a boolean value.

  • Each expression is preceded by a | and followed by an =
  • The value on the right side of the = is evaluated only if the expression on the left side evaluates to True.
  • Instead of using _ for our catch all (because all our expressions must evaluate to boolean values), we use otherwise. otherwise is defined as the value True.

You’d want to use a guard when there are more than 2 or more specific expressions you want to evaluate with a specific result to return for each one.

party'' :: String -> String
party'' food
  | food == "pizza"    = "hooray pizza party!"
  | food == "noodles"  = "oooooo we could make ramen"
  | food == "popcorn"  = "popcorn & movie night!"
  | otherwise          = "that's not party food"

otherwise is used by convention to make guards more readable. Just to prove that otherwise is just True we can rewrite our function with the value instead of the variable.

party''' :: String -> String
party''' food
  | food == "pizza"    = "hooray pizza party!"
  | food == "noodles"  = "oooooo we could make ramen"
  | food == "popcorn"  = "popcorn & movie night!"
  | True               = "that's not party food"
About Author :

I am Pavankumar, Having 8.5 years of experience currently working in Video/Live Analytics project.

Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions