Functions in Haskell

A function is nothing but a block of code, which we can use in our programs by calling them. When we call a function, the function code becomes part of the program.

Most of the time functions are used for calculating things, or to perform repetitive steps, or making the programs more modular.

Importance :

For example, consider the block of code that calculates the distance between Earth and moon in Kilometers (KM), and you have written this code 75 times throughout your application.

But one fine day, you are realizing that you wanted to write the distance should be in Miles rather than Kilometers.

The only way you can rectify it is, you have to go to all the places(75) and edit them.

Same Through function :

Consider you have written the same code inside a function and you have used the same function all the places of application by calling it.

Now, you want to change the distance in terms of Miles, Guess how many places you have to change the result. Yes, Only one place, that is in the function

Functions Based on Creation :

  • Present in Package
  • User-created

Present in Package

There are functions which comes along with packages of Haskell, something like sqrt.

For example, we might want to use the Prelude's sqrt function, which computes the square root of a floating-point value. To compute √5, for instance, we can simply type the following into the interpreter, and it would print back the return value.

ghci>sqrt 5.0

//Output : 2.23606797749979

Note that when we call a function in Haskell, we do not place parentheses around the parameter. Of course, we could if we wanted, but they would be redundant. Since Haskell programs use lots of functions, it's convenient to leave them out.

If we want we can include the parenthesis when it is necessary or to reduce the confusion to the user.

sqrt (3 * 3 + 4 * 4)	returns 5.0
sqrt (3 ** 2 + 4 ** 2)	returns 5.0

Functions with multiple Arguments :

Many functions take multiple arguments. Two examples are the max function for computing the maximum of two numbers and the rem function for computing the remainder of dividing two integers.

max 3.0 3.5
rem 17 5

Notice that we're again not using parentheses to surround the arguments. They would be necessary, however, if we want to use a function to compute the argument to another function.

max 3.0 (sqrt 5.0)

Without the parentheses, the interpreter would parse this as an attempt to pass three arguments into max: 3.0, sqrt, and 5.0.

The interpreter would complain that the expression doesn't type-check: The max function expects two numeric arguments, and it's being told to pass it three arguments, and with the second argument as a function (sqrt), not a number.

User-defined Function

User-defined functions are nothing but the function that we create for our application. Now suppose, we want to define a function — maybe a addNumbers function that adds its argument. That's easy enough to do.

addNumbers  x = x + x

A function definition has an equals sign separating its header(aka name) from the expression saying how to compute the return value.

The header in this case is simply a prototype for a function call: In this case, we're saying that we're defining addNumbers that takes a single parameter x.

Now suppose we load this function into our interpreter. (With Hugs, that would involve writing the above into a file with a text editor and then instructing Hugs to load the file).

We would then be able to use the function just as we can use the functions defined in the Prelude.

addNumbers  3 5

Pattern Matching / Polymorphism in Haskell

In the context of purely functional languages and of this page, PatternMatching is a dispatch mechanism: choosing which variant of a function is the correct one to call. Inspired by standard mathematical notations.

A feature of FunctionalProgramming and LogicProgramming languages, which is fundamental to making these programming paradigms declarative rather than imperative.

factorial(0) ::= 1
factorial(n) ::= n * factorial(n-1)

The factorial function has been given two definitions. Which is used for dispatch when a call is made will depend, in this case, on whether the actual parameter pattern matches 0 or not.

If arguments match 0 then factorial(0) ::= 1 will get a call, if the argument is other than 0 then I will match with factorial(n) ::= n * factorial(n-1)

Pattern matching is the compiler's ability to compare both the form and the content of two expressions.

Recursive function with Haskell

A recursive function is a function that calls itself during its execution. This enables the function to repeat itself several times, outputting the result and the end of each iteration.

factorial 0 = 1
factorial n = n * factorial (n - 1)

Now you can call the factorial function like factorial 4, now compiler tries to find out the exact match for the function. The given value is not 0, so factorial 0 = 1 will not receive a call, the factorial n = n * factorial (n - 1) receives the call and return n * factorial (n - 1). In this return, we have factorial (n - 1) which again calls the factorial function but the value will be n -1, so each time the value gets reduced. When the value reaches 0, the factorial n = n * factorial (n - 1) will not receive the but factorial 0 = 1 receive the call and return 1.

So the end may look like below.

factorial 4.

4 * factorial 3
4 * 3 * factorial 2
4 * 3* 2 * factorial 1
4 * 3* 2 * 1 * factorial 0
// Actual output
4 * 3 * 2 * 1 * 1 => 24

Infinite loops :

Recursive functions are common in computer science because they allow programmers to write efficient programs using a minimal amount of code. The downside is that they can cause infinite loops and other unexpected results if not written properly.

In the above code, if you skip writing factorial 0 = 1 then you will get an infinite loop and causes the following error.

*** Exception: stack overflow

Haskell multi-line function

Multi-line function will have more than one line of block and works without issues. Start by setting Ghci into multiline mode with:

:set +m

You can start a multi-line block with :{ and end it with :}. Function definitions must be preceded with let. This has tripped me up many times.

For example, to define a function that pauses for a given delay before printing out “done":

  let printAfter :: Int -> IO ()
      printAfter delay =
        do putStrLn $ (\d -> "waiting for " ++ d ++ " microseconds") $ show delay
           threadDelay delay
           putStrLn "done"

To unset multi-line mode use:

:unset +m
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