0% found this document useful (0 votes)
40 views22 pages

FP UNIT1 Notes

The document introduces functional programming by defining it, comparing it to other paradigms like imperative and object-oriented programming, and discussing pure and impure approaches. Functional programming uses mathematical functions instead of stateful procedures and immutable data. It aims to be more predictable and flexible than other paradigms.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
40 views22 pages

FP UNIT1 Notes

The document introduces functional programming by defining it, comparing it to other paradigms like imperative and object-oriented programming, and discussing pure and impure approaches. Functional programming uses mathematical functions instead of stateful procedures and immutable data. It aims to be more predictable and flexible than other paradigms.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 22

Functional Programming (KR20)

UNIT - 1
Syllabus:
Introducing Functional Programming: Defining Functional Programming, Considering Other
Programming Paradigms, Using Functional Programming to Perform Tasks, Discovering
Languages That Support Functional Programming.
Getting and Using Haskell: Working with Haskell, Obtaining and Installing Haskell,
Compiling a Haskell Application, Using Haskell Libraries, Getting Help with the Haskell
Language.
Defining the Functional Difference: Comparing Declarations to Procedures, Understanding
How Data Works, Seeing a Function in Haskell, Seeing a Function in Python
_____________________________________________________________________________

Introducing Functional Programming


Functional Programming Paradigm is a framework that expresses a particular set of assumptions,
relies on particular ways of thinking through problems, and uses particular methodologies to
solve those problems. The math orientation of functional programming means that one cannot
create an application using it; instead one can use it to solve straightforward math problems or
devise what if scenarios to test.

Defining Functional Programming


Functional programming has somewhat different goals and approaches than other paradigms use.
Goals define what the functional programming paradigm is trying to do in forging the
approaches used by languages that support it. However, the goals don’t specify a particular
implementation; doing that is within the purview of the individual languages.

The main difference between the functional programming paradigm and other paradigms is that
functional programs use math functions rather than statements to express ideas. This difference
means that rather than write a precise set of steps to solve a problem, use math functions, and
don’t worry about how the language performs the task. In some respects, this makes languages
that support the functional programming paradigm similar to applications such as MATLAB.

Using this approach to defining a problem relies on the declarative programming style, which is
used with other paradigms and languages, such as Structured Query Language (SQL) for
database management. In contrast to other paradigms, the functional programming paradigm
doesn’t maintain state. The use of state enables to track values between function calls. Other
paradigms use state to produce variant results based on environment, such as determining the
number of existing objects and doing something different when the number of objects is zero. As
a result, calling a functional program function always produces the same result given a particular
set of inputs, thereby making functional programs more predictable than those that support state.

Prepared by: Afreen Fatima Mohammed 1 KMIT


Functional Programming (KR20)

Because functional programs don’t maintain state, the data they work with is also immutable,
which means that one cannot change it. To change a variable’s value, one must create a new
variable. Again, this makes functional programs more predictable than other approaches and
could make functional programs easier to run on multiple processors.

Understanding its goals


Imperative programming, is akin to an assembly line, where data moves through a series of steps
in a specific order to produce a particular result. The process is fixed and rigid, and the one
implementing the process must build a new assembly line every time an application requires a
new result.

Object-oriented programming (OOP) simply modularizes and hides the steps, but the underlying
paradigm is the same. Even with modularization, OOP often doesn’t allow rearrangement of the
object code in unanticipated ways because of the underlying interdependencies of the code.

Functional programming gets rid of the interdependencies by replacing procedures with pure
functions, which requires the use of immutable state. Consequently, the assembly line no longer
exists; an application can manipulate data using the same methodologies used in pure math. The
seeming restriction of immutable state provides the means to allow anyone who understands the
math of a situation to also create an application to perform the math.

Using pure functions creates a flexible environment in which code order depends on the
underlying math. That math models a real-world environment, and as our understanding of that
environment changes and evolves, the math model and functional code can change with it —
without the usual problems of brittleness that cause imperative code to fail.

Modifying functional code is faster and less error prone because the person implementing the
change must understand only the math and doesn’t need to know how the underlying code
works. In addition, learning how to create functional code can be faster as long as the person
understands the math model and its relationship to the real world.

Functional programming also embraces a number of unique coding approaches, such as the
capability to pass a function to another function as input. This capability enables to change
application behavior in a predictable manner that isn’t possible using other programming
paradigms.

Using the Pure approach


Programming languages that use the pure approach to the functional programming paradigm rely
on lambda calculus principles, for the most part. In addition, a pure-approach language allows
the use of functional programming techniques only, so that the result is always a functional
program.

Example of pure-approach language is Haskell because it provides the purest implementation.


Other pure-approach languages include Lisp, Racket, Erlang, and OCaml.

Prepared by: Afreen Fatima Mohammed 2 KMIT


Functional Programming (KR20)

Using the Impure approach


Many developers use a language that mixes functional features with one of the other
programming paradigms . For example, functional programming features can be found in
languages such as C++, C#, and Java.
When working with an impure language, code won’t work in a purely functional manner. For
example, one cannot pass a function to another function in some languages. The use of multiple
programming paradigms makes Python quite flexible , popular and flexible easy to learn.

______________________________________________________________________________

Considering Other Programming Paradigms


There are different paradigms which represents a different approach to the solution for the
problems by using a particular methodology while making assumptions about things like
developer expertise and execution environment. The different paradigms are discussed below:
.
Imperative
Imperative programming takes a step-by-step approach to perform a task. The developer
provides commands that describe precisely how to perform the task from beginning to end.
During the process of executing the commands, the code also modifies application state, which
includes the application data. The code runs from beginning to end. An imperative application
closely mimics the computer hardware, which executes machine code. Machine code is the
lowest set of instructions that you can create and is mimicked in early languages, such as
assembler.

Procedural
Procedural programming implements imperative programming, but adds functionality such as
code blocks and procedures for breaking up the code. The compiler or interpreter still ends up
producing machine code that runs step by step, but the use of procedures makes it easier for a
developer to follow the code and understand how it works. Many procedural languages provide a
disassembly mode in which you can see the correspondence between the higher-level language
and the underlying assembler. Examples of languages that implement the procedural paradigm
are C and Pascal.
Early languages, such as Basic, used the imperative model because developers creating the
languages worked closely with the computer hardware. However, Basic users often faced a
problem called spaghetti code, which made large applications appear to be one monolithic piece.
Consequently, languages that follow the procedural paradigm are a step up from languages that
follow the imperative paradigm alone.

Object-oriented
The procedural paradigm does make reading code easier. However, the relationship between the
code and the underlying hardware still makes it hard to relate what the code is doing to the real

Prepared by: Afreen Fatima Mohammed 3 KMIT


Functional Programming (KR20)

world. The object-oriented paradigm uses the concept of objects to hide the code, but more
important, to make modeling the real world easier. A developer creates code objects that mimic
the real-world objects they emulate. These objects include properties, methods, and events to
allow the object to behave in a particular manner. Examples of languages that implement the
object-oriented paradigm are C++ and Java.

Languages that implement the object-oriented paradigms also implement both the procedural and
imperative paradigms. The fact that objects hide the use of these other paradigms doesn’t mean
that a developer hasn’t written code to create the object using these older paradigms.
Consequently, the object-oriented paradigm still relies on code that modifies application state,
but could also allow for modifying variable data.

Declarative
Functional programming actually implements the declarative programming paradigm, but the
two paradigms are separate. Other paradigms, such as logic programming, implemented by the
Prolog language, also support the declarative programming paradigm.
The short view of declarative programming is that it does the following:

»»Describes what the code should do, rather than how to do it.
»»Defines functions that are referentially transparent (without side effects).
»»Provides a clear correspondence to mathematical logic.

_____________________________________________________________________________

Using Functional Programming to Perform Tasks


Functional programming is a paradigm, which means that it doesn’t have an implementation.
The basis of functional programming is lambda calculus which is actually a math abstraction.
Consequently, when one wants to perform tasks by using the functional programming paradigm,
that means that, they are looking for a programming language that implements functional
programming in a manner that meets one’s needs. In addition to using lambda functions,
languages that implement the functional programming paradigm have some other features in
common.
Overview of common features are:

»»First-class and higher-order functions: First-class and higher-order functions both


allow to provide a function as an input.

»»Pure functions: A pure function has no side effects. When working with a pure function,
one can
• Remove the function if no other functions rely on its output
• Obtain the same results every time a function is called with a given set of inputs
• Reverse the order of calls to different functions without any change to application functionality
• Process the function calls in parallel without any consequence

Prepared by: Afreen Fatima Mohammed 4 KMIT


Functional Programming (KR20)

• Evaluate the function calls in any order, assuming that the entire language doesn’t allow side
effects
»»Recursion: Functional language implementations rely on recursion to implement looping.
In general, recursion works differently in functional languages because no change in application
state occurs.
»»Referential transparency: The value of a variable never changes in a functional
language implementation because functional languages lack an assignment operator.

Some languages use strict (eager) evaluation, while other languages use non-strict (lazy)
evaluation.

Under strict evaluation, the language fully checks the function before evaluating it. Even when
a term within the function isn’t used, a failing term will cause the function as a whole to fail.

However, under non-strict evaluation, the function fails only if the failing term is used to create
an output. The Miranda, Clean, and Haskell languages all implement non-strict evaluation.
______________________________________________________________________________

Discovering Languages That Support Functional


Programming
The functional programming paradigm supports two kinds of language implementation, pure and
impure.
Considering the pure languages
A pure functional programming language is one that implements only the functional
programming paradigm. Functional programming is mutually exclusive to programming
paradigms that have anything to do with the imperative paradigm.

Considering the impure languages


Python is likely the epitome of the impure language because it supports so many coding styles.
One can code in whatever style one need at the moment. The definition of an impure language
is one that doesn’t follow the rules for the functional programming paradigm fully.

For example, allowing any modification of application state would instantly disqualify a
language from consideration. One of the more common and less understood reasons for
disqualifying a language as being a pure implementation of the functional programming
paradigm is the lack of pure-function support. A pure function defines a specific relationship
between inputs and outputs that has no side effects. Every call to a pure function with specific
inputs always garners precisely the same output, making pure functions extremely reliable.
______________________________________________________________________________

Prepared by: Afreen Fatima Mohammed 5 KMIT


Functional Programming (KR20)

Getting and Using Haskell


• Haskell needs a different installation to meet specific needs or tool requirements. After
installing Haskell , one can perform some simple coding tasks using it.
• The main purpose of writing a code is to verify that Haskell which is installed is
working properly and also helps to familiarize us with Haskell.

Working with Haskell


Various tools work with Haskell configured in different ways. Different platforms support
different options. Haskell is both highly flexible and relatively new, so stability issues need to be
considered. To ensure that the code works well, use the 8.2.2 version of Haskell. Older versions
may lack features or require bug fixes.
_____________________________________________________________________________

Obtaining and Installing Haskell


 Obtain Haskell for each of the three platforms supported at
https://www.haskell.org/platform/prior.html
 Simply click the icon corresponding to the platform of your choice.
 The page takes to the section that corresponds with the platform.
 In all three cases, perform full installation, rather than a core installation, because the
core installation doesn’t provide support for some of the packages.
 Both Mac and Windows users can use only a 64-bit installation.
 Mac users should rely on the installer, rather than use Homebrew Cask.
 Linux users should rely on the 64-bit installation to obtain better results.
 Make sure that you have plenty of drive space for installation.
 For example, even though the Windows download file is only 269MB, the Haskell
Platform folder will consume 2.6GB of drive space after the installation is complete.You
can encounter a problem when clicking the links on the initial page. If you find that the
download won’t start, go to https://downloads.haskell.org/~platform/8.2.2/ instead and
choose the particular link for your platform:
»»Generic Linux: Haskell-platform-8.2.2-unknown-posix--full-i386.tar.gz
»»Specific Linux: See the installation instructions in the “Installing Haskell on a Linux system”
section that follows
»»Mac: Haskell Platform 8.2.2 Full 64bit-signed.pkg
»»Windows: HaskellPlatform-8.2.2-full-x86_64-setup.exe
Haskell supports some Linux distributions directly. If this is the case then don’t need to
download a copy of the product.

Installing Haskell on a Linux system


Use the $ sudo apt-get command or tarball for generic Linux. The specific Linux installations
are:
»»Ubuntu
»»Debian

Prepared by: Afreen Fatima Mohammed 6 KMIT


Functional Programming (KR20)

»»Linux Mint
»»Redhat
»»Fedora
»»Gentoo
Download the tarball and follow these instructions to install it:
1. Type tar xf haskell-platform-8.2.2-unknown-posix--full-i386.tar.gz and press Enter.
The system extracts the required files.
2. Type sudo ./install-haskell-platform.sh and press Enter.

Installing Haskell on a Mac system


When working with a Mac platform, access a Haskell installer specifically designed for a Mac.
The following steps describe how to perform the installation using the graphical installer:

1. Locate the downloaded copy of Haskell Platform 8.2.2 Full 64bit-signed.pkg on your
system.
2. Double-click the installation file.
Haskell Platform 8.2.2 64-bit Setup dialog box will appear.
3. Click Next.
The wizard displays a licensing agreement.
4. Click I Agree if you agree to the licensing agreement.
The setup wizard asks where you want to install your copy of Haskell.
5. Click Next.
A dialog box asking which features to install will appear
6. Click Next.
A new dialog box will appear that asks where to install the Haskell Stack. Use the default
installation location to ensure that setup works correctly.
7. Click Next.
The setup wizard asks which features to install. Install all of them.
8. Click Install.
You see the Haskell Stack Setup wizard complete.
9. Click Close.
You see the Haskell Platform wizard progress indicator move. At some point, the installation
completes.
10. Click Next.
You see a completion dialog box.
11. Click Finish.
Haskell is now ready for use on your system.

Installing Haskell on a Windows system:


When working with a Windows platform, access a Haskell installer specifically designed for
Windows. The following steps assume that you’ve downloaded the required file.
1. Locate the downloaded copy of HaskellPlatform-8.2.2-full-x86_64-setup.exe on your
system.

Prepared by: Afreen Fatima Mohammed 7 KMIT


Functional Programming (KR20)

2. Double-click the installation file.


See an Haskell Platform 8.2.2 64-bit Setup dialog box.
3. Click Next.
The wizard displays a licensing agreement.
4. Click I Agree if you agree to the licensing agreement.
The setup wizard asks where you want to install your copy of Haskell, as shown in Figure 3-1.

5. Optionally provide an installation location and then click Next.


You see a dialog box asking which features to install. Note especially the Update System settings
option. You must ensure that this option is selected to obtain proper functioning of the Haskell
features.

6. Choose the features you want to use and click Next.

Prepared by: Afreen Fatima Mohammed 8 KMIT


Functional Programming (KR20)

The setup wizard asks you which Start menu folder to use, as shown in Figure 3-3.

7. Optionally type a new Start menu folder name and click Install.
A new dialog box appear that asks where to install the Haskell Stack.

8. Optionally type a new location and click Next.


The setup wizard asks you which features to install. You must install all of them.
9. Click Install.
You see the Haskell Stack Setup wizard complete.
10. Click Close.
You see the Haskell Platform wizard progress indicator move. At some point, the installation
completes.
11. Click Next.
You see a completion dialog box.
12. Click Finish.
Haskell is now ready for use on your system.

Testing the Haskell Installation


There is an access to a considerable number of environments for working with Haskell. Using
Linux or Mac platforms, rely on an add-in for the Jupyter Notebook environment used for
Python. Use Glasgow Haskell Compiler interpreter (GHCi) that comes with the Haskell
installation. Windows users have a graphical interface they can use called WinGHCi that works
precisely the same as GHCi, but with a nicer appearance, as shown in Figure 3-4.
Find either GHCi or WinGHCi in the folder, to store the Haskell application icons on your
system. When working with Windows, find this file at Start ➪ All Programs ➪ Haskell

Prepared by: Afreen Fatima Mohammed 9 KMIT


Functional Programming (KR20)

Platform 8.2.2. No matter how the interpreter is opened , the version number of installation can
be seen, as shown in Figure 3-4.

The interpreter can provide a great deal of information about Haskell. The commands all start
with a colon, including the help commands. So to start the process, you type :? and press Enter.
Figure 3-5 shows typical results.

As look through the list all commands beginning with a colon, can be seen. For example, to exit
the Haskell interpreter, type :quit and press Enter. Type "Haskell is fun!" and press Enter. See
the string repeated onscreen, as shown in Figure 3-6. All Haskell has done is evaluate the string
which was provided. As a next step, try creating a variable by typing x = "Haskell is really
fun!" and press Enter. This time, Haskell doesn’t interpret the information but simply places the
string in x

Prepared by: Afreen Fatima Mohammed 10 KMIT


Functional Programming (KR20)

To see the string, use the putStrLn function. Type putStrLn x and press Enter. Figure 3-7 shows
what is seen. At this point, it will be known that the Haskell installation works.

______________________________________________

Compiling a Haskell Application


Using the interpreter, you can also load modules and interpret them. To see how this works,
create a text file on your system called Simple.hs. Use a pure text editor, such as Notepad or
TextEdit.

Type the following code into the file and save it on disk:

Prepared by: Afreen Fatima Mohammed 11 KMIT


Functional Programming (KR20)

main = putStrLn out


where
out = "5! = " ++ show result
result = fac 5
fac 0 = 1
fac n = n * fac (n - 1)

To compile a Haskell application, there must be a main function, which consists of a single
statement, which in this case is putStrLn out. The variable out is defined as part of the where
clause as the concatenation of a string, "5! = ", and an integer, result, that is outputted using the
show function. The code must be indented, to compile correctly.

The code calculates the result by using the fac (factorial) function that appears below the main
function. The first line defines the stopping point. When the input is equal to 0, the function
outputs a value of 1. Otherwise, the second line is used to call fac recursively, with each
succeeding call reducing the value of n by 1 until n reaches 0. After the file is saved , open GHCi
or WinGHCi, to experiment with the application.

The following steps provide the means to load, test, and compile the application:

1. Type :cd <Source Code Directory> and press Enter.


Supply the location of the source code on your system.
2. Type :load Simple.hs and press Enter.
Notice that the prompt changes to *Main>, as shown in Figure 3-8. If WinGHCi is used , we
can also use the File ➪ Load menu command to accomplish this task.

3. Type :main and press Enter.

Prepared by: Afreen Fatima Mohammed 12 KMIT


Functional Programming (KR20)

The output of the application is shown in Figure 3-9. When working with WinGHCi, we can also
use the Actions ➪ Run “main” command or we can click the red button with the right-pointing
arrow on the toolbar.

4. Type :! ghc --make ″Simple.hs″ and press Enter.


The interpreter now compiles the application, as shown in Figure 3-10. We see a new executable
created in the source code directory. When working with WinGHCi, we can also use the Tools
➪ GHC Compiler menu command to perform this task. We can now execute the application at
the command prompt and get the same results as we did in the interpreter.

5. Type :module and press Enter.


This act unloads all the existing modules. Notice that the prompt changes back to Prelude>. You
can also perform this task using the Actions ➪ Clear Modules menu command.
6. Type :quit and press Enter.
The interpreter closes.
______________________________________________________________________________

Prepared by: Afreen Fatima Mohammed 13 KMIT


Functional Programming (KR20)

Using Haskell Libraries


Haskell has a huge library support base in which you can find all sorts of useful functions. Using
library code is a time saver because libraries usually contain well-constructed and debugged
code. The import function allows you to use external code. The following steps take you through
a simple library usage example:
1. Open GHCi, if necessary.
2. Type import Data.Char and press Enter.
Note that the prompt changes to Prelude Data.Char> to show that the import is successful. The
Data.Char library contains functions for working with the Char data type. See a listing of these
functions at http://hackage.haskell.org/package/base-4.11.1.0/docs/Data-Char.html.
3. Use the ord function to convert a character to its ASCII numeric representation.
Type ord(′a′) and press Enter.
The output value of 97 is resulted.
_____________________________________________________________________________

Getting Help with the Haskell Language


The documentation that the wizard installs as part of Haskell setup is the first place one should
look when have questions. There are three separate files for answering questions about: GHC,
GHC flags, and the Haskell libraries. In addition, a link for HackageDB, which is the Haskell
Software Repository where one can get packages such as Datasets.
Tutorials make learning any language a lot easier. Fortunately, the Haskell community has
created many tutorials that take different approaches to learning the language at
https://wiki.haskell.org/Tutorials.
. However, one of the better places to look for help is StackOverflow at
https://stackoverflow.com/search?q=haskell.
______________________________________________________________________________

Defining the Functional Difference


We use declarations —formal or explicit statements describing the problem — instead of
procedures — step-by-step problem solutions. To make the functional paradigm work, the code
must manage data differently than when using other paradigms. The fact that functions can occur
in any order and at any time (allowing for parallel execution, among other things) means that
functional languages can’t allow mutable variables that maintain any sort of state or provide side
effects.

Comparing Declarations to Procedures


The term declaration has a number of meanings in computer science, and different people use
the term in different ways at different times. For example, in the context of a language such as C,
a declaration is a language construct that defines the properties associated with an identifier. We
can see declarations used for defining all sorts of language constructs, such as types and
enumerations.

Prepared by: Afreen Fatima Mohammed 14 KMIT


Functional Programming (KR20)

For example, consider the following statement:


Make me a cup of tea!
The statement tells simply what to do, not how to do it. The declaration leaves the execution of
the task to the party receiving it and infers that the party knows how to complete the task without
additional aid. Most important, a declaration enables someone to perform the required task in
multiple ways without ever changing the declaration. However, when using a procedure named
MakeMeTea (the identifier associated with the procedure), you might use the following sequence
instead:
1. Go to the kitchen.
2. Get out the teapot.
3. Add water to the teapot.
4. Bring the pot to a boil.
5. Get out a teacup.
6. Place a teabag in the teacup.
7. Pour hot water over the teabag and let steep for five minutes.
8. Remove the teabag from the cup.
9. Bring me the tea.
A procedure details what to do, when to do it, and how to do it. The steps appear in a specific
order, and performing a step out of order will cause problems.
Procedures are often error prone and inflexible, but they do allow for precise control over the
execution of a task. Declarations do suffer from another sort of inflexibility, however, in that
they don’t allow for interpretation. When making a declarative statement (“Make me a cup of
tea!”), we can be sure that the recipient will bring a cup of tea and not a cup of coffee instead.

However, when creating a procedure, we can add conditions that rely on state to affect output.
For example, we might add a step to the procedure that checks the time of day. If it’s evening,
the recipient might return coffee instead of tea, knowing that the requestor always drinks coffee
in the evening based on the steps in the procedure. A procedure therefore offers flexibility in its
capability to interpret conditions based on state and provide an alternative output. Declarations
are quite strict with regard to input. The example declaration says that a cup of tea is needed, not
a pot or a mug of tea. The MakeMeTea procedure,however, can adapt to allow variable inputs,
which further changes its behavior.

One of the hardest issues in moving from imperative languages to functional languages is the
concept of declaration. For a given input, a functional language will produce the same output and
won’t modify or use application state in any way. A declaration always serves a specific purpose
and only that purpose.
The second hardest issue is the loss of control. The language decides how to perform tasks, not
the developer.
______________________________________________________________________________
\
Understanding How Data Works
Data is a representation of something — perhaps a value. However, it can just as easily represent
a real-world object. The data itself is always abstract, and existing computer technology

Prepared by: Afreen Fatima Mohammed 15 KMIT


Functional Programming (KR20)

represents it as a number. Even a character is a number: The letter A is actually represented as


the number 65. The letter is a value, and the number is the representation of that value: the data.

Working with immutable data


Being able to change the content of a variable is problematic in many languages. The memory
location used by the variable is important. If the data in a particular memory location changes,
the value of the variable pointing to that memory location changes as well. The concept of
immutable data requires that specific memory locations remain untainted. All Haskell data is
immutable. Python data, on the other hand, isn’t immutable in all cases. When working with
Python code, we use id function to determine when changes have occurred to variables.

For example, in the following code, the output of the comparison between id(x) and oldID
will be false:

x=1
oldID = id(x)
x=x+1
id(x) == oldID

The id of a variable is always guaranteed unique except in certain circumstances:


»»One variable goes out of scope and another is created in the same location.
»»The application is using multiprocessing and the two variables exist on different processors.
»»The interpreter in use doesn’t follow the CPython approach to handling variables.

When working with other languages, we need to consider whether the data supported by that
language is actually immutable and what set of events occurs when code tries to modify that
data. In Haskell, modifications aren’t possible, and in Python, we can detect changes, but not all
languages support the functionality required to ensure that immutability is maintained.

Considering the role of state


Application state is a condition that occurs when the application performs tasks that modify
global data. An application doesn’t have state when using functional programming. The lack of
state has the positive effect of ensuring that any call to a function will produce the same results
for a given input every time, regardless of when the application calls the function.
However, the lack of state has a negative effect as well: The application now has no memory.
When we think about state, think about the capability to remember what occurred in the past,
which, in the case of an application, is stored as global data.

Eliminating side effects


Procedures can’t return a value. The declaration “Make me a cup of tea!” has only one output:
the cup of tea. The procedure has a side effect instead of a value. After making a cup of tea, the
procedure indicates that the recipient of the request should take the cup of tea to the requestor.
However, the procedure must successfully conclude for this event to occur. The procedure isn’t
returning the tea; the recipient of the request is performing that task. Consequently, the procedure

Prepared by: Afreen Fatima Mohammed 16 KMIT


Functional Programming (KR20)

isn’t returning a value. Side effects also occur in data. When we pass a variable to a function, the
expectation in functional programming is that the variable’s data will remain untouched —
immutable. A side effect occurs when the function modifies the variable data so that upon return
from the function call, the variable changes in some manner.

______________________________________________________________________________
Seeing a Function in Haskell
Haskell is all about functions, it supports a lot of function types. It does demonstrate two of the
more important function types (non-curried and curried).

Using non-curried functions


We can look at non-curried functions as Haskell’s form of the standard function found in other
languages.
To create a standard function, we provide a function description like this one:
add (x, y) = x + y
TTo use this function, you simply type something like add (1, 2) and press Enter.
Figure 4-1 shows the result.

Functions can act as the basis for other functions. Incrementing a number is really just a special
form of addition.
Consequently, you can create the inc function shown here:
inc (x) = add (x, 1)
As you can see, add is the basis for inc. Using inc is as simple as typing something like inc 5 and
pressing Enter. Note that the parentheses are optional, but you could also type inc (5) and press
Enter. Figure 4-2 shows the result.

Prepared by: Afreen Fatima Mohammed 17 KMIT


Functional Programming (KR20)

Using curried functions


Currying in Haskell is the process of transforming a function that takes multiple arguments into a
function that takes just one argument and returns another function when additional arguments are
required.
Begin by opening a new window and creating a new version of add, as shown here:
add x y = x + y
Notice that the arguments don’t appear in parentheses and have no comma between them. The
function content still appears the same, however. To use this function, you simply type
something like add 1 2 and press Enter. Figure 4-3 shows the result.

We don’t actually see the true effect of currying, though, until you create the inc function. The
inc function really does look different, and the effects are even more significant when function
complexity increases:
inc = add 1
This form of the inc function is shorter and actually a bit easier to read. It works the same way as
the non-curried version. Simply type something like inc 5 and press Enter to see the result shown
in Figure 4-4.

Prepared by: Afreen Fatima Mohammed 18 KMIT


Functional Programming (KR20)

Interestingly enough, we can convert between curried and non-curried versions of a function as
needed using the built-in curry and uncurry functions.
Try it with add by typing uadd = uncurry add and pressing Enter. To prove to ourself that uadd
is indeed the non-curried form of add, type uadd 1 2 and press Enter.
You see the error shown in Figure 4-5.

We can use curried functions in some places where non-curried functions won’t work. The map
function is one of these situations.
The following code adds a value of 1 to each of the members of the list:
map (add 1) [1, 2, 3]
The output is [2,3,4] as expected. Trying to perform the same task using uadd results in an error,
as shown in Figure 4-6.

Prepared by: Afreen Fatima Mohammed 19 KMIT


Functional Programming (KR20)

______________________________________________
Seeing a Function in Python
Functions in Python look much like functions in other languages.
Creating and using a Python function
Python relies on the def keyword to define a function.
For example, to create a function that adds two numbers together, you can use the
following code:
def add(x, y):
return x + y
To use this function, we can type something like add(1, 2). Figure 4-7 shows the output of this
code when we run it in Notebook.

Prepared by: Afreen Fatima Mohammed 20 KMIT


Functional Programming (KR20)

As with Haskell, we can use Python functions as the basis for defining other functions.
For example, here is the Python version of inc:
def inc(x):
return add(x, 1)
The inc function simply adds 1 to the value of any number. To use it, we might type something
like inc(5) and then run the code, as shown in Figure 4-8, using Notebook.

Pass by reference versus by value


The point at which Python shows itself to be an impure language is the use of passing by
reference. When we pass a variable by reference, it means that any change to the variable within
the function results in a global change to the variable’s value. In short, using pass by reference
produces a side effect, which isn’t allowed when using the functional programming paradigm.
Normally, we can write functions in Python that don’t cause the passing by reference problem.
For example, the following code doesn’t modify x, even though you might expect it to:
def DoChange(x, y):
x = x.__add__(y)
return x
x=1
print(x)
print(DoChange(x, 2))
print(x)
The value of x outside the function remains unchanged.

For example, the following code will modify the output:


def DoChange(aList):
aList.append(4)
return aList
aList = [1, 2, 3]
print(aList)
print(DoChange(aList))
print(aList)
The appended version will become permanent in this case because the built-in function, append,
performs the modification.

Prepared by: Afreen Fatima Mohammed 21 KMIT


Functional Programming (KR20)

To avoid this problem, we must create a new variable within the function, change its value, and
then return the new variable, as shown in the following code:
def DoChange(aList):
newList = aList.copy()
newList.append(4)
return newList
aList = [1, 2, 3]
print(aList)
print(DoChange(aList))
print(aList)
Figure 4-9 shows the results. In the first case, we see the changed list, but the second case keeps
the list intact.

Prepared by: Afreen Fatima Mohammed 22 KMIT

You might also like