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.
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)
True or False.
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 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.
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 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.
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"
I am Pavankumar, Having 8.5 years of experience currently working in Video/Live Analytics project.