Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
66 views

Functional Programming

- Functional programming is characterized by programming with values, functions, and functional forms. Functional programming languages are the result of abstracting and generalizing the mapping of elements in a domain to a range. - The lambda calculus is a simple yet expressive language that is the basis for functional programming languages. It allows defining anonymous functions using lambda abstraction and function application. - Functional programming has advantages for concurrency, artificial intelligence applications, prototyping, and its theoretical foundations in the lambda calculus. Core concepts include recursion, higher-order functions, lazy evaluation, and fixed point combinators.

Uploaded by

maryam arshad
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
66 views

Functional Programming

- Functional programming is characterized by programming with values, functions, and functional forms. Functional programming languages are the result of abstracting and generalizing the mapping of elements in a domain to a range. - The lambda calculus is a simple yet expressive language that is the basis for functional programming languages. It allows defining anonymous functions using lambda abstraction and function application. - Functional programming has advantages for concurrency, artificial intelligence applications, prototyping, and its theoretical foundations in the lambda calculus. Core concepts include recursion, higher-order functions, lazy evaluation, and fixed point combinators.

Uploaded by

maryam arshad
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 27

Functional Programming

Functional programming is characterized by the programming with values, functions and functional forms.
Functional programming languages are the result of both abstracting and generalizing the data type of maps.
Recall, the mapping m from each element x of S (called the domain) to the corresponding element m(x) of T
(called the range) is written as:
m : S --> T
For example, the squaring function is a function of type:
sqr : Num --> Num
and may be defined as:
sqr where x |--> x*x
A linear function f of type
f : Num --> Num
may be defined as:
f where x |--> 3*x + 4
The function:
g where x |--> 3*x2 + 4

may be written as the composition of the functions f and sqr as:


f \circ sqr
were
f \circ sqr (x) = f(sqr(x)) = f (x*x) = 3 * x2 + 4
The basic concepts of functional programming originated with LISP. Functional
programming languages are important for the following reasons.
● Functional programming has natural implementation in concurrent programming.
● Functional programming has important application areas. Artificial intelligence programming is
done in functional programming languages and the AI techniques migrate to real-world
applications.
● Functional programming is useful for developing executable specifications and prototype
implementations.
● Functional programming has a close relationship to computer science theory. Functional
programming is based on the lambda-calculus which in turn provides a framework for studying
decidability questions of programming
The Lambda Calculus
Functional programming languages are based on the lambda-calculus. The lambda-calculus is a
simple language with few constructs and a simple semantics. But it is expressive; it is sufficiently
powerful to express all computable functions.
As an informal example of the lambda-calculus, consider the function defined by the polynomial
expression
x2 + 3x - 5.
The variable x is a parameter. In the lambda-calculus, the notation \x.M is used to denote a function
with parameter x and body M. That is, x is mapped to M. We rewrite our function in this format
\x.(x2+ 3x - 5)
and read it as ``the function of x whose value is defined by x2 + 3x - 5''. The
lambda-calculus uses prefix form and so we rewrite the body in prefix form,
\x. (- (+ (× x x) (× 3 x)) 5).
The lambda-calculus curries its functions of more than one variable i.e. (+ x y) is written as ((+ x) y), the
function (+ x) is the function which adds something to x. Rewriting our example in this form we get:
\x.((- ((+ ((× x) x)) ((× 3) x))) 5)
To denote the application of a function f to an argument a we write
fa
To apply our example to the value 1 we write
\x.((- ((+ ((× x) x)) ((× 3) x))) 5) 1.
To evaluate the function application, we remove the \x. and replace each remaining
occurrence of x with 1 to get
((- ((+ ((× 1) 1)) ((× 3) 1))) 5)
then evaluate the two multiplication expressions
((- ((+ 1) 3)) 5)
then the addition
((- 4) 5)
and finally, the subtraction
-1
Operational Semantics
Calculation in the lambda-calculus is by rewriting (reducing) a lambda-expression to a
normal form. For the pure lambda-calculus, lambda-expressions are reduced by substitution.
That is, occurrences of the parameter in the body are replaced with (copies of) the argument.
In our extended lambda-calculus we also apply the usual reduction rules. For example,
1. \x.(x2 - 5) 3 f(3) where f(x) = x2 - 5
2. 32 - 5 by substitution
3. 9 - 5 power
4. 4 subtraction
Definition: A lambda-expression is said to be in normal form if no beta-redex, a subexpression of
the form (\x.P Q ), occurs in it.
Reduction Order
Given a lambda-expression, the substitution and beta-reduction rules provide the tools required to reduce
a lambda-expression to normal form but do not tell us what order to apply the reductions when more than
one redux is available. The following theorem, due to Curry, states that if an expression has a normal
form, then that normal form can be found by leftmost reduction.
Theorem: If E has a normal form N, then there is a leftmost reduction of E to N.
A function is strict if it is sure to need its argument. If a function is non-strict, we say that it
is lazy.
parameter passing by value, by name, and lazy evaluation
Infinite Data Structures
call by need
streams and perpetual processes
A function f is strict if and only if (f _|_) = _|_
Scheme evaluates its parameters before passing (eliminates need for renaming) a space and time
efficiency consideration.
Recursive Functions
We extend the syntax of the lambda-calculus to include named expressions as follows:
Lambda Expressions
L ::= ...| x : L | ...
where x is the name of the lambda-expression L.
With the introduction of named expressions we have the potential for recursive definitions since the
extended syntax permits us to name lambda-abstractions and then refer to them within a lambda
expression. Consider the following recursive definition of the factorial function.
FAC : \n.(if (= n 0) 1 (* n (FAC (- n 1))))
which with syntactic sugaring is
FAC : \n.if (n = 0) then 1 else (n * FAC (n - 1))
We can treat the recursive call as a free variable and replace the previous definition with the
following.
FAC : (\fac.(\n.(if (= n 0) (* n (fac (- n 1))))) FAC)
Let
H : \fac.(\n.(if (= n 0) 1 (* n (fac (- n 1)))))
Note that H is not recursively defined. Now we can redefine FAC as
FAC : (H FAC)
This definition is like a mathematical equation. It states that when the function H is applied to
FAC, the result is FAC. We say that FAC is a fixed point or fixpoint of H. In general functions
may have more than one fixed point. In this case the desired fixed point is the mathematical
function factorial. In general, the `right' fixed point turns out to be the unique least fixed point.
It is desirable that there be a function which applied to a lambda-abstraction returns the least fixed point of
that abstraction. Suppose there is such a function Y were,
FAC : Y H
Y is called a fixed point combinator. With the function Y, this definition of FAC does not
use of recursion. From the previous two definitions, the function Y has the property that
Y H = H (Y H)
As an example, here is the computation of FAC 1 using the Y combinator.
FAC 1 = (Y H) 1
= H (Y H) 1
= \fac.(\n.(if (= n 0) 1 (* n (fac (- n 1))))) (Y H) 1
= \n.(if (= n 0) 1 (* n((Y H)(- n 1)))) 1
= if (= 1 0) 1 (* 1 ((Y H)(-11)))
= (* 1 ((Y H)(-11)))
= (* 1 ((Y H)0))
= (* 1 (H (Y H) 0))
...
= (* 1 1)
=1
The function Y can be defined in the lambda-calculus.
Y : \h.(\x.(h (x x)) \x.(h (x x)))
It is especially interesting because it is defined as a lambda-abstraction without using
recursion. To show that this lambda-expression properly defines the Y combinator, here it is
applied to H.
(Y H) = (\h.(\x.(h (x x)) \x.(h (x x))) H)
= (\x.(H (x x)) \x.(H (x x)))
= H ( \x.(H (x x))\x.(H (x x)))
= H (Y H)
THANK YOU

You might also like