Contact

Technologies

What is the concept of a functional language also adopted by Scala? Learn its characteristics in the pure functional language Haskell.

2023.05.16

Author : Kenta Inoue

What is a functional language?

Although it is difficult to clearly define a functional language, this article considers the following.

While procedural languages are mainly programmed by combining statements and instructions, functional languages are mainly written by combining expressions and functions.

Now, to compare the differences between procedural and functional languages, let's see a program that computes the least common multiple of integers n1 and n2.

Procedural language written in "statements"

First, we will look at java, a procedural language.

public class GCD { public static void main(String[] args) { final int n1 = 15; final int n2 = 10; int n = n1; int m = n2; int k; System.out.println(n); // n == 15 while (m > 0){ k = m; m = n % m; n = k; } System.out.println(n); // n == 5 } }

The program is made by combining statements such as assignment and while statements. In addition, because the value of a variable changes due to assignment, the same instruction statement may produce different output, as in the above System.out.println(n) output result is 15 before the while statement and 5 after. (We will explain this in more detail later.)

In contrast, we see the case in a functional language.

Functional language written in "expressions"

The program to find the least common multiple in the functional language Haskell is shown as follows.

n1 :: Int n1 = 15 n2 :: Int n2 = 10 euclid :: Int -> Int -> Int euclid n m = if m == 0 then n else euclid m $ n `mod` m -- euclid m (n `mod` n) main :: IO () main = print $ euclid n1 n2 -- print (euclid n1 n2)

In functional languages, there is no such thing as a while statement, but rather a combination of expressions and functions. In the example above, euclid and print in the main function are functions, and euclid n1 n2 and print $ euclid n1 n2 are expressions. Even with such a combination of functions and expressions, the same program can be written as in a procedural language, i.e., it is guaranteed to be Turing-complete, and the program-writing capability remains the same.

Reference permeability and side effects

Writing only expressions, as in Haskell, means that variables are not rewritten as in assignment statements. This means that all variable values and functions are defined only at the time of declaration and cannot be rewritten later in an immutable declaration. This specification is reference-transparent and has no side-effects, as follows The specification is reference-transparent, meaning that the same arguments passed to the same function will always return the same result, and side-effects, meaning that other external variables or state can be rewritten within the function.

So, to summarize briefly

  • reference-transparent:Not affected by outside influences.
  • No side-effects:No external influence.

That is to say. A function that satisfies both of these is called a pure function, and a functional language in which (almost) all functions are pure functions, such as Haskell, is called a pure functional language.

At first glance, a pure functional language would seem incapable of performing these operations, since programs that include external inputs and outputs are, in principle, not reference-transparent and will contain side effects. However, if it is possible to separate the pure part from the part where these inputs and outputs occur, it can be called a pure functional language. In fact, this is achieved by utilizing monads and the like. (That is what I mean by almost all functions being pure.)


Focus on reference transparency

Scala, which is also sometimes called a functional language, is not a pure functional language due to its object-oriented aspect, but it is one of the languages that is highly aware of referential transparency: it is either mutable or immutable, which means that it cannot be changed afterwards. In fact, there are two types of variable definitions, mutable var and immutable val, and libraries are also separated into mutable and immutable.

Programs in languages that satisfy referential transparency have the following characteristics.

Characteristics of languages that satisfy referential transparency

Characteristics of programs that satisfy referential transparency, such as Haskell, include the following.

Easy to test and fix bugs.

In the case of a program that satisfies referential transparency, since the value of a variable or the execution of a function does not change depending on the context, only a single test can be completed, and when an error occurs, only its definition needs to be checked, making bug correction relatively easy. For programs that do not satisfy referential transparency, their output may depend on the context, so when a bug occurs, it may be necessary to check not only the definition but also the context before and after it, which requires more time and effort.

Easy to perform parallel processing.

In a program that satisfies referential transparency, each function always returns the same value for the same input, regardless of the order of execution. Therefore, if the input values are the same, it is guaranteed that the result will not change even if parallel processing is performed. In non-reference-transparent languages, the return value may vary depending on the order of program execution, and some programs are not suitable for parallel processing.

Need to consider the compatibility with external input/output.

When there are inputs and outputs such as external databases, functions that read no longer satisfy referential transparency, and functions that rewrite no longer satisfy purity in principle because of side effects that affect the outside world. Therefore, the question becomes how to handle such functions. In the case of the pure functional language Haskell, a mechanism called a monad is used to separate functions that are not transparent to references such as external input/output and functions with side effects from pure functions for internal processing, allowing programming while maintaining the purity of internal processing. This mechanism called Monad will be explained in detail in another article.


Refer to how to write functional languages.

As we saw in the previous example, one feature of the pure functional language Haskell was its guaranteed referential transparency. That is, it consists only of functions whose return values are always the same if the inputs are the same. This has the above advantages and makes it possible to create referentially transparent programs to some extent even in a procedural language.

Be aware of reference transparency.

In general, writing an assignment statement itself can cause side effects. Therefore, let's try to write the java example as shown in the previous section without using assignment statements.

public class GCD { public static void main(String[] args) { final int n1 = 15; final int n2 = 10; System.out.println(euclid(n1,n2)); } public static int euclid(int n, int m) { int k; while (m != 0){ k = m; m = n % m; n = k; } return n; } public static int euclid2(int n, int m) { if (m == 0) { return n; } else { return euclid2(m,(n % m)); } } public static int euclid3(int n, int m) { return (m == 0) ? n : euclid3(m,(n % m)); } }

Let's isolate the euclid function from the original program; the first simply isolates it and changes the values of the arguments n,m and the internal variable k. The second isolates it and changes the values of the arguments n,m and the internal variable k. Basically, if you try to write a loop statement, it will be rewritten, and internally there will be side effects. In other words, the loop statement is considered to have a side effect, which is why repeating the same instruction causes changes and brings meaning to the statement. However, euclid itself does not depend on or rewrite external variables, making euclid a pure function that is reference transparent.

In functional languages, recursive calls are used instead of loops, and euclid2 is aware of this. In this function, there are no side effects because there are no assignments to variables, and the appearance is similar to a program in Haskell. However, to be more precise, an if statement is not an expression but a statement, so euclid3, which is written as an expression using the ternary operator, is the most functional-like description. However, there is no need to be so particular about making it look like a functional language. In practical use, it is enough to make the first euclid function transparent by reference.


Other features of functional languages.

Other features include higher-order functions, i.e., the ability to take function arguments, return a function as the return value, and take type arguments. However, this is not a feature of functional languages, but rather a feature of the specification of each language that is independent of the language type, so it is not specifically explained in this article. (Certainly, higher-order functions can be written in most functional languages and are often used.)


Summary

The concept of functional languages adopted by languages such as Scala was explained, as well as what functional languages are in the first place and their characteristics.


Back to index


Join Us

Recruit


We have an ambition like "we open up the future with technology we carry out into the world"and are established with continuing effort to become a leading company in the industry.
Because of being a young company, it will with all the employees who join the company be able to realize that we make history with all the employees who join the company.
We are currently executing hiring activity.
With Nihon Insight Technologies carrying out the technology into the world, you are expected to perform all the capability you have.


New Graduate
Mid Career


Contact Us

Contact


Contact