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

Functional Programming

The document discusses different types of objects in programming languages based on their capabilities. First class objects can be used without restriction, passed as parameters, returned from functions, etc. Second class objects cannot be assigned to variables or returned from functions, while third class objects cannot be passed as parameters. Functional programming relies on first class functions, which allow functions to be treated as objects that can be passed to other functions. Higher order functions take functions as parameters or return functions. Type inference algorithms like Damas-Milner use type constraints and unification to infer types in a polymorphic way. Functional programming is based on evaluation of expressions without side effects, unlike imperative programming which can change state.

Uploaded by

Tanvi Sharma
Copyright
© © All Rights Reserved
Available Formats
Download as RTF, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
57 views

Functional Programming

The document discusses different types of objects in programming languages based on their capabilities. First class objects can be used without restriction, passed as parameters, returned from functions, etc. Second class objects cannot be assigned to variables or returned from functions, while third class objects cannot be passed as parameters. Functional programming relies on first class functions, which allow functions to be treated as objects that can be passed to other functions. Higher order functions take functions as parameters or return functions. Type inference algorithms like Damas-Milner use type constraints and unification to infer types in a polymorphic way. Functional programming is based on evaluation of expressions without side effects, unlike imperative programming which can change state.

Uploaded by

Tanvi Sharma
Copyright
© © All Rights Reserved
Available Formats
Download as RTF, PDF, TXT or read online on Scribd
You are on page 1/ 7

FUNCTIONAL PROGRAMMING

Different Classes of Objects


A classification of entities one can find in a program by what can be done with them.
First class: can be used without restriction. Example: integers in C++ or any other
language.
Second class: cannot be assigned to a variable or returned by functions. Example: Classes
in Smalltalk.
Third class: cannot be passed as function parameters. Example: data types in C++.
Properties of First Class Objects
Expressible as an anonymous literal value
Storable in variables
Storable in data structures
Having an intrinsic identity (independent of any given name)
Comparable for equality with other entities
Passable as a parameter to a function
Returnable as the result of a function call
Constructable at runtime
First Class Functions
First-class functions are a necessity for the functional programming style, in which the use of
higher-order functions is a standard practice. A simple example of a higher-ordered
function is the map function, which takes, as its arguments, a function and a list, and
returns the list formed by applying the function to each member of the list. For a
language to support map, it must support passing a function as an argument.
Languages vary as to what is FirstClass. Some, such as the C Language have only basic types
(ints, pointers; in particular, arrays are not truly FirstClass though the array/pointer
equivalence lets you fake it in most situations). In ObjectOriented languages such as C+
+, objects are FirstClass but classes are not, while in SmalltalkLanguage or
RubyLanguage, for example, all references including references to class objects are
FirstClass. In FunctionalProgramming, functions are FirstClass.
A programming language supports first class functions if it allows functions to be first class
objects. Supported by all functional languages: Lisp, Scheme, ML, as well as many of the
interpreted languages: Python, Perl, JavaScript. Creating a function at runtime means
your program must contain a compiler. In C++ only function references (pointers) are
first class objects.
Higher-Order Functions
A higher-order function accepts functions as arguments and is able to return a function as its
result. A higher-order language supports higher-order functions and allows functions to
be constituents of data structures.
In mathematics and computer science, a higher-order function (also functional, functional
form or functor) is a function that does at least one of the following:
takes one or more functions as arguments,

returns a function as its result.


All other functions are first-order functions. In mathematics higher-order functions are also
known as operators or functionals. The differential operator in calculus is a common
example, since it maps a function to its derivative, also a function.
What, exactly, do we mean by the 'order of functions'. This is explained in below.
The order of data
Order 0: Non function data
Order 1: Functions with domain and range of order 0
Order 2: Functions with domain and range of order 1
Order k: Functions with domain and range of order k-1
Higher-order functions allow us to abstract over actions, not just values. They come in
several forms. For example, you can have functions that create new functions.
function greaterThan(n) {
return function(m) { return m > n; };
}
var greaterThan10 = greaterThan(10);
console.log(greaterThan10(11));
// true
And you can have functions that change other functions.
function noisy(f) {
return function(arg) {
console.log("calling with", arg);
var val = f(arg);
console.log("called with", arg, "- got", val);
return val;
};
}
noisy(Boolean)(0);
// calling with 0
// called with 0 - got false
.
Lambda Expressions
Also called anonymous functions or methods.
They describe functions by directly describing their behavior.
These expressions were Inspired from lambda calculus, a branch of mathematics that studies
functions, recursion, computability. Invented by A. Church in 1930.
Its Present in many languages like C#, Python, Perl.
Usually lambda expressions mean that the language allows first class functions.
Types
SML programming language has a large repertoire of types, including primitive types like

int, real and bool, and compound types built from other types using type constructors,
such as int * int, bool * int * real, int -> int, and int list. For each type there is a set of
values of that type. Values of type int correspond to mathematical integers. Values of type
int list are (finite) lists of integers. In SML you can only evaluate an expression if the
expression is well-typed, i.e., has a type.
Similarly, you can only use a declaration if it is well-typed, and when this happens the
declaration introduces bindings that associate types to names throughout a syntactically
determined region.
You can only use an expression, value or a bound name, in a manner that fits with its type.
Type-checking
Type-checking involves figuring out if an expression has a specific type. Given an expression
e and a type t it is pretty simple to check if e has type t, by appealing to some syntaxdirected type rules. For example:
A numeral, such as 0 or 1, has type int.
The infix arithmetic operators + and * can be used on two integers, or on two reals:
e1+e2 has type int if and only if e1 and e2 have type int.
e1*e2 has type int if and only if e1 and e2 have type int.
e1+e2 has type real if and only if e1 and e2 have type real.
e1*e2 has type real if and only if e1 and e2 have type real.
Strong Typing
This means that every value has a defined type, and we can check that type before evaluating
the value. Benefits
- many errors are caught before run-time
- use types to categorise and lookup functions
A type may be monomorphic, polymorphic, or an instance of a type class.
Note: we can always make a monomorphic instance of a polymorphic type.
E.g.
length :: [a] -> Int
(polymorphic)
lengthInt :: [Int] -> Int (monomorphic)
Type Checking Function Definitions
To check a function f :: t1 -> t2 -> -> tk -> t
when there are several cases, i.e.
f p1 p2 pk
| g1 = e1
| g2 = e2

| gl = el
We need to check that
- each of the guards gi is of type Bool
- the value of each ei is of type t
- each pattern pj matches some element of type tj.
E.g.
pattern p:q matches an element of type [t] when

p matches an element of t and q matches an


element of [t].
Example
f :: Int -> [Int] -> Int
f a (x:xs)
| (a>x) = a + x
| (a ==x) = x
Note:
| (x >xs) = a
type error
Can we deduce type of f?
Let (x:xs):: [b], then x::b. a has same type as x, so a::b. b must be numeric, assume b=Int.
f:: t1 -> t2 -> t3
p1=a,
so p1 matches an element of Int
p2=x:xs
so p2 matches an element of [b] = [Int]
e1=a + x, a has type Int
So f :: Int -> [Int] -> Int
Polymorphic Type Checking
Type checking a polymorphic type is the same as solving type constraints.
Some examples:
Consider f (x,y) = (x,[a .. y])
(a pair)
(a character)
- the argument to f is a pair
- x is completely unconstrained
- y is an expression in an enumerated type, starting with a Char, so y must have type Char
- [a .. y] has type [Char]
- the rhs is a pair.
Therefore, f :: (a,Char) -> (a, [Char])
Consider g (m,zs) = m + length zs
a pair
adds values
[b] -> Int
- m must have a numeric type
- zs must be a list type, call it [b]
- length zs :: Int, so this forces m to have type Int
- since m has type Int, the rhs must have type Int
- we dont know anything else about zs.
Therefore, g :: (Int,[b]) -> Int.

Function Composition

TYPE INFERENCE

The advantages of strong static typing, where types are inferred by the compiler at compile
time, are now generally recognized. As a matter of fact languages such as Haskell, ML,
Mercury or Java all rely on strong typing. In order to gain programming flexibility
avoiding rejecting perfectly safe programs, the type inference algorithm should support
type polymorphism, i.e. it should allow programs to possess more than one type. Two
main options for polymorphism are universal types, where types are parametrized (this
concept is known as parametric polymorphism), and intersection types which introduce
an operator of intersection over types (their duals are the existential types and union
types).
The most popular type inference algorithm is the Damas-Milner algorithm which supports
parametric polymorphism with universal types. In the area of type systems for
programming languages there was a long search for systems more expressive than the
Damas-Milner type system and with decidable typability. In this search there have been a
few positive results in two distinct directions: extensions of the Damas-Milner approach
and systems based on intersection types
Type inference in all these systems rely on some notion of constraint resolution. The type
inference algorithm of the Damas-Milner system (used as the basis of the type systems of
functional programming languages such as ML and Haskell), uses unification to solve
constraints in the type language. Several extensions of this algorithm are based on
extensions of the unification algorithms with some kind of constraint resolution
mechanism.

Imperative vs. functional programming

Two different programming language paradigms:


Imperative (aka. procedural): here the execution of a program is both evaluation of
expressions and changing a state (values of variables).
This involves "stateful" programming and evaluation can have side effects.
Functional: here the execution of a program is just evaluation of expressions, without
changing the values of variables.
This involves "stateless" programming
No side effects in this case. and States and side effects have a double effect:
It enables efficient time and space consumption

Structure of a functional program

The levels in functional programming paradigm are

modules

definitions
expressions
How is polymorphism used in functional programming languages?

Parametric polymorphism is a form of polymorphism where function types are parametric.


This is the most common in functional programming and hugely necessary for Haskell
and SML.
Ad-hoc polymorphism is most commonly seen in things like operator overloading in C++.
Use in functional programming
With parametric polymorphism, a function can had the same body but operate on several
types. Take for instance two simple, non-polymorphic functions for identity written in
Haskell.
idInts :: Int -> Int
idInt x = x
idString :: String -> String
idString x = x
Here we would need to define the identity function for every type we want to use it on even
though they have the exact same implementation. In real Haskell code we can use a
parametric type, here expressed with a lower-case letter to declare that it works on any
type. By convention, in Haskell, the letter a is used for "any" or "all types".
id :: a -> a
id x = x
This now works for all types and we only have to do it once. Here's an example of the type
for the ever present map function.
map :: (a -> b) -> [a] -> [b]
This function has two unspecified types, a and b. Both can be any type at all but notice that
your first argument, which is a function from a to b (a->b) must match the types of the
list that is the second argument [a] and the list that is output [b].

You might also like