Functional programming model Functional Programming
and supporting languages appeared very early as soon as the concept of Declarative Programming
appeared in the field of software programming in general. However, due to its heavy load of features borrowed from Mathematics, it is somewhat less friendly than Procedural Programming
in terms of accessibility to potential programmers who are not from academic environments. Therefore, programming languages based entirely on Functional Programming
are often less popular and almost unknown to the majority of programmers before 2010.
However, that does not mean that Functional Programming
is more difficult than Procedural Programming
, or requires users to have a strong Math background. And even with a friendly self-study guide, with a slight slight on borrowed concepts from Mathematics, anyone can begin to learn, use, and see the effect that their way of thinking. Functional Programming
provides.
Therefore, in the years after 2010, a series of popular programming languages such as JavaScript (ECMA 2015)
, Java 8 (Java 2014)
, etc. have brought in new updated versions of Functional
features to Help programmers write more concise, beautiful, and intuitive code. At the present time, perhaps no one is unaware Funtional Programming
and a few related coding techniques such as lambda
expressions, curry
parameters, …
Haskell Language
In the group of purely Functional
languages, there are two languages that are considered to represent two schools of using different syntax to express Functional
programming thinking, namely Haskell
and LISP
. Among them, Haskell
is said to have a more user-friendly syntax for programmers who are familiar with popular programming languages. The reason is because the syntax of LISP
is designed to be closer to the logic of computer reading, and here is an example of the function that calculates the value of the n
element in the Fibonaci
sequence being placed on the LISP
homepage:
1 2 3 4 5 6 | (defun fib (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))) |
We’ll soon be rewriting this fib
function ourselves using Haskell
‘s syntax, but first a short excerpt of the language’s history. Haskell
was first introduced in 1990, several years earlier than the Java
and JavaScript
brothers (1995). This pure Functional
language was designed by a team of programming engineers of nearly two dozen people and is named after the American mathematician and scientist Haskell Brooks Curry
. This Sir is very well known in the academic environment at home and in addition to Haskell
, the words Brooks
and Curry
are also used to name other programming languages, most of which are used in academic training and applications. industrial use.
And so, until about the years after 2010, the programming community in the world in general could not ignore the Funtional Programming
that made Haskell
become a highly influential language. Specifically, special module
like LINQ/C#
and Generics/Java
are all designed with syntax and referential thinking from Haskell
. Some other languages that have received influence from Haskell
include Scala
, Swift
, Visual Basic 9.0
, C++ 11
, F#
, Rust
, Elm
, PureScript
, etc..
Among them, Elm
and PureScript
are typical names that are also designed purely Functional
with syntax similar to Haskell
about ~ 90%
. The rest of the difference is because of the features that Haskell
supports and Elm
and PureScript
do not at the moment.
Hello, Haskell!
There are so many great things about Haskell
and its development environment that we wouldn’t be able to list them all in one article. So it’s best to start right away with the Hello World
code and the filename Main.hs
– which can be created with MS Notepad
or any other code editor.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">module</span> <span class="token constant">Main</span> <span class="token keyword">where</span> <span class="token hvariable">main</span> <span class="token operator">::</span> <span class="token constant">IO</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token builtin">putStrLn</span> <span class="token hvariable">message</span> <span class="token keyword">where</span> <span class="token hvariable">message</span> <span class="token operator">=</span> <span class="token hvariable">hello</span> <span class="token string">"Haskell"</span> <span class="token hvariable">hello</span> <span class="token operator">::</span> <span class="token constant">String</span> <span class="token operator">-></span> <span class="token constant">String</span> <span class="token hvariable">hello</span> <span class="token hvariable">name</span> <span class="token operator">=</span> <span class="token string">"Hello, "</span> <span class="token operator">++</span> <span class="token hvariable">name</span> <span class="token operator">++</span> <span class="token string">" !"</span> |
You can test the starter code in the online code execution environment here: REPLit.com . We’ll talk about installing the Haskell
-specific development environment in the next section of the article.
We have a Hello, World
program that starts at main
function which is defined by a data type declaration line with no input parameters and returns a value of type IO ()
, and a line describing The detailed operating logic is that main
will delegate work to the putStrLn
function, which is already defined in the Haskell
standard library. Compared to Elm
, the type declaration operation in Haskell
is only different in that the ::
notation is used to separate the function name and the type information of the parameters and return values. In Elm
we only use 01 colon :
.
The putStrLn
function requires as an input a String
string stored in the message
variable, and the determination of the printed string is further delegated to the self-defined hello
function with the input parameter name
and type String
and the return result. about is the body of the full greeting which is also of type String
.
So the final result that we get after running the main
function is a value of type IO ()
that has been defined by Haskell
. As for how the logic will convert this value into a logic that makes the state change of the Console
window, it is already implemented in the compiler
and we don’t need to care.
Thus, the basic syntax of Haskell
is not strange if you have accompanied me in the Sub-Series Elm
. The main
function is supported by other functions in the form of a computed expression and returns some result, rather than a description of the steps to be taken. A program written in Haskell
will only be filled with function calls in expressions like this, and so function calls are designed to look pretty natural – without the parentheses like C
or JavaScript
.
1 2 3 4 5 6 7 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><stdio.h></span></span> <span class="token keyword">void</span> <span class="token function">main</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">char</span> <span class="token operator">*</span> message <span class="token operator">=</span> <span class="token function">hello</span> <span class="token punctuation">(</span> <span class="token string">"C"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">"%s"</span> <span class="token punctuation">,</span> message <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Instead of writing pure Imperative
statements describing the operation of calculating the string content to be printed first, and then running the printf
procedure to print the content to the Console
window; Then in Haskell
we write code in the form of Declarative
declaration to define main
briefly as putStrLn message
, and then continue to provide a detailed definition of the mesage
in the next line with the keyword where
is message = hello "Haskell"
.
This is something Elm
doesn’t have, and Elm
only supports the let .. in
construct which is also borrowed from Haskell
but will make reading the code harder to follow in a Declarative
mindset, because we’ll have to read the definition. Details about the message
first, then read the rest of the main
function. If we have many attached elements similar to the message
, then when we want to skim through and extract the most concise definition information, main = text message
to check the data type declaration of the main
function, we will have to Specifies the last line in the let .. in
in block to extract information describing the right side of the regex.
1 2 3 4 5 6 7 8 | <span class="token keyword">module</span> <span class="token constant">Main</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span> <span class="token hvariable">main</span> <span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Html <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span> <span class="token constant">Html</span> <span class="token punctuation">,</span> <span class="token hvariable">text</span> <span class="token punctuation">)</span> <span class="token hvariable">main</span> <span class="token operator">:</span> <span class="token constant">Html</span> <span class="token hvariable">message</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token keyword">let</span> <span class="token hvariable">message</span> <span class="token operator">=</span> <span class="token hvariable">hello</span> <span class="token string">"Elm"</span> <span class="token keyword">in</span> <span class="token hvariable">text</span> <span class="token hvariable">message</span> |
Of course, we can also stack function calls by pushing the priority of function calls behind with parentheses ()
like in other popular programming languages instead of using the construct binding
with where
or let .. in
.
1 2 3 4 5 6 7 8 | <span class="token keyword">module</span> <span class="token constant">Main</span> <span class="token keyword">where</span> <span class="token hvariable">main</span> <span class="token operator">::</span> <span class="token constant">IO</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token builtin">putStrLn</span> <span class="token punctuation">(</span> <span class="token hvariable">hello</span> <span class="token string">"Haskell"</span> <span class="token punctuation">)</span> <span class="token hvariable">hello</span> <span class="token operator">::</span> <span class="token constant">String</span> <span class="token operator">-></span> <span class="token constant">String</span> <span class="token hvariable">hello</span> <span class="token hvariable">name</span> <span class="token operator">=</span> <span class="token string">"Hello, "</span> <span class="token operator">++</span> <span class="token hvariable">name</span> <span class="token operator">++</span> <span class="token string">" !"</span> |
Now the call to the hello
function is written after putStrLn
but will be executed first due to the precedence of the parentheses ()
surrounding the passed parameter. And we can see the first feature of Functional Programming
that sub-program
will always return a certain value, not directly creating side-effect
on environmental elements. outside school.
Even the built-in putStrLn
function will return a value of type IO ()
and can be passed to other function calls to perform calculations if necessary. The side-effect
logic will be implemented automatically by the compiler similar to Elm
which will return a data structure describing a single page SPA
, but about the generated HTML
and JS
files like anyway will be optimized at the compiler level and the coder will not need to care about designing the procedure
that does the job.
That’s why using a purely Functional Programming
language in a specifically designed environment will have a vastly different experience than borrowing from Functional
tools and using it in suboptimal Imperative
environments. for Functional Programming
.
This is similar to writing Procedural
code in Ada
which is much more convenient than borrowing tools like contract
and then bringing it to popular languages that are not fully optimized for Procedural Programming
. Tools borrowed into environments that are not optimally designed for a particular programming paradigm will always have limitations in terms of functionality and readability of the syntax used.
Haskell Setup
To start installing the Haskell
development toolkit on any operating system, simply open the official Haskell
website at: Haskell.org -> GHC-up
. The command to download and activate the GHC-up
installer for the operating system you are using will appear right in the To install on ...
panel of the website. All we need to do is copy this installation command and enter it into the command line window of the operating system we are using.
With Windows
it would be Powershell
:
1 2 | Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; try { Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true } catch { Write-Error $_ } |
As for Linux
, it will be Terminal
:
1 2 | curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh |
After that, the installation process will bring up some menus asking about the tools you want to install, so we just install all of them including the Stack
project manager and HLS - Haskell Language Server
. For example, if you want to install additional plug-in
for VS Code
to support syntax recognition and proofing in Haskell
code files, the HLS
will definitely be needed. For Windows
, the installer will suggest installing the MSYS2
to use bash
commands like Linux
and installing more is not cumbersome. Just install it fully because there will be a time when you will need to use it.
After the installation is complete, we can type the command to check the version of the GHC
compiler to confirm that the installation was successful.
1 2 3 4 5 6 7 | ghc --version The Glorious Glasgow Haskell Compilation System, version 9.2 cabal --version cabal-install version 3.6 compiled using version 3.6 of the Cabal library |
And then proceed to compile and run the code of the
main.hs
file created in the previous example.1 2 3 4 5 6 | cd Desktop ghc Main.hs Main Hello, Haskell ! |