CA341 - Comparative Programming Languages Functional Programming Paradigm

CA341 - Comparative Programming Languages Functional Programming Paradigm

Functional Programming Paradigm CA341 - Comparative Programming Languages Functional Programming Paradigm David Sinclair Functional Programming Paradigm Key Concepts of Functional Programming The key concepts of functional programming are: • Expressions • Functions • Parametric Polymorphism • Data Abstractions • Lazy Evaluation Expressions are used to compute new values from old values. Functions, which are first-class values, abstract over expressions. Functions can be passed as arguments to functions and computed as a result of other functions. A higher-order function is one that takes other functions as arguments or computed another functions as a result. Functions can be built into composite values. Functional Programming Paradigm Key Concepts of Functional Programming (2) Parametric polymorphism is when a function operates on values of a type family rather than just one type. It is fundamental to the power and expressiveness of functional languages. Data abstraction is common in most of the modern functional languages, such as ML and Haskell. Lazy evaluation relates to when an expression is evaluated. There are three different ways to define the order in which expressions are evaluated. • Eager evaluation • Normal-order evaluation • Lazy evaluation Functional Programming Paradigm Evaluation Order In eager evaluation we evaluate the actual parameters once at the point of call. The effect is to substitute the actual argument value for each occurrence of the formal parameter. In normal-order evaluation we evaluate the actual parameter only when the argument is actually needed. The effect is to substitute the actual unevaluated parameter for each occurrence of the formal parameter. Consider the function sqr n = n ∗ n invoked as sqr(m+1) where m has the value 6. Functional Programming Paradigm Evaluation Order (2) In eager evaluation we first evaluate m+1 which evaluates to 7. The value 7 is then bound to n. Evaluation n*n results in evaluating 7*7 as 49. In normal-order evaluation we first bind the unevaluated expression m+1 to n, resulting in the expression (m+1) * (m+1) that yields the expression (6+1) * (6+1), which yields 49. In the case of the sqr function, either evaluation order results in the same result though eager evaluation is more efficient as the expression (m+1) is only evaluated once. But this is not always the case! Consider the function cand b1 b2 = i f b1 then b2 else False Functional Programming Paradigm Evaluation Order (3) Suppose we invoke cand (n>0) (t/n>50) with n bound to 2 and t bound to 80. With eager evaluation n>0 yields True and t/n>50 yields False, and the function call yields False. With normal-order evaluation the function call effectively evaluates i f (2 >0) then (80/2 >50) else False which also yields False. Now suppose we invoke cand (n>0) (t/n>50) with n bound to 0 and t bound to 80. With eager evaluation n>0 yields False but the evaluation of t/n>50 fails due to a divide by zero error. Hence the function call fails. Functional Programming Paradigm Evaluation Order (4) With normal-order evaluation the function call effectively evaluates i f (0 >0) then (80/0 >50) else False which evaluate 0>0 as False. Since expression 80/0>50 does not need to be evaluated, the function call returns False. A function is strict in a particular argument if it always uses that argument. In our examples, the sqr function is strict in its argument n, whereas cand is strict in its first argument but nonstrict in its second argument. Functional Programming Paradigm Evaluation Order (5) Having an expression that evaluates differently depending on the evaluation order can be problematical. Some programming languages have an important property called the Church-Rosser Property, which states that: If an expression can be evaluated at all, it can be evaluated by consistently using normal-order evaluation. If an expression can be evaluated in several different orders (mixing eager and normal-order evaluation), then all of these evalution orders yield the same result. Haskell possesses the Church-Rosser Property, but any language that has side-effects (such as ML, C++, Java etc) does not possess the Church-Rosser Property. In practice normal-order evaluation is too inefficient as its actual parameters might be evaluated several times, all yielding the same argument. Functional Programming Paradigm Evaluation Order (6) In lazy evaluation we evaluate the actual parameter when the argument is first needed and then store its value for whenever it is subsequently needed. If the programming language possesses the Church-Rosser Property then lazy evaluation always results in the same values as normal-order evaluation. Lazy evaluation is adopted only by pure functional languages such as Haskell. Other languages (most languages!) adopt eager evaluation. An interesting effect of lazy evaluation is that we can define potentially infinite data structures since the evaluation of any expression is delayed until its value is actually needed. In Haskell we can define an infinite list of integers. The contents of the infinite list are not evaluated. The 500th element (and its preceding 499 elements) of the list is not evaluated until it is actually needed. Functional Programming Paradigm The Pragmatics of Functional Programming Languages A functional programming language is composed of many functions, which are in turn composed of simpler functions, which eventually are composed of expressions and declarations. A pure functional programming language does not use commands, proper procedures that update variables. Instead, a functional programming language gains its power and expressiveness from concepts such as higher-order functions and lazy evalution. A large functional program has a very large number of functions and managing them can be problematical. Many functional languages provide a mechanism to group functions into packages Functional Programming Paradigm Haskell Haskell was design in the 1980’s by a committee led by Simon Peyton Jones and John Hughes. It was influenced by ML (from which it took parametric polymorphism and type inference) and Miranda (from which it took lazy evaluation). Haskell is a pure functional language; no variables, sequencers or side-effects (though modelling state and input/output is possible using a concept called a monoid). The power of Haskell comes from its use of higher-order functions and lazy evaluation. Functional Programming Paradigm Haskell: Values and Types Haskell has the usual set of primitive types such as Bool, Char and numeric types (integers and floating-point). As a result of lazy evaluation, Haskell has both a bounded integer type, Int, and an unbounded integer type, Integer. Haskell also has the usual collection of composite types: tuples, algebraic types (disjoint unions), lists and functions. Recursive types can be defined directly. The most commonly used composite type in a Haskell program is the list. The type [t] are lists whose elements are of type t. [] denotes the empty list and x:xs constructs a list whose head (the first element) is x and tail (the list containing the remaining elements) is xs. Functional Programming Paradigm Haskell: Values and Types (2) Haskell has a large library of functions on lists. These functions demonstrates parametric polymorphism in Haskell. For example, head :: [t] −> t −− head xs computes the head of list xs of type t tail :: [t] −> [ t ] −− tail xs computes the tail of the list xs of type t length :: [t] −> I n t −− length xs computes the length of list xs ++ :: [t] −> [ t ] −> [ t ] −− xs ++ ys computes the concatenation of lists xs and ys All of these functions can operate on lists of any type t. Functional Programming Paradigm Haskell: Functions A function has a name and a set of parameters, each separated by a space. How the function is evaluated is defined by what follows the = symbol. This only tells part of the story of the rectangleArea function. • A function always evaluates to a value which has a type. • Each of the parameters of a function have a type. rectangleArea :: Float −> Float −> Float rectangleArea x y = x ∗ y The parameters and return type are separated by -> in the function declaration. The return type is the last item and the parameter types are the previous items. Functional Programming Paradigm Haskell: Functions (2) insert : : I n t −> [ I n t ] −> [ I n t ] insert i [] = [i] insert i (n:ns) = i f i < n then i:n:ns else n : insert i ns In an imperative language a similar procedure would insert the new element by selectively updating the existing list. In Haskell the function must compute a new list containing the new element as well as the original elements. Though the function seems to copy the entire original list, it actually only copies the “nodes” containing integer less than i. The remaining nodes are shared between list and the new list. Functional Programming Paradigm Haskell: Functions (3) Even though the original list is shared, because a functional programmer cannot manipulate the “links between the nodes”, the lists are effectively distinct. This does not only apply to lists but to any recursive type, such as trees. Haskell does not have any in-built support for arrays. This is because while a recursive type that differs by a single element can share a lot of their structure, this is not true of arrays. If a function modifies an array it would have to copy the original array (there is a Haskell library module that supports arrays). The simplest form of function construction is \I -> E, whose formal parameter is I and whose body is the expression E. Functional Programming Paradigm Haskell: Functions (4) A Haskell function call has the form E1 E2 where E1 is an expression that yields a function and E2 is an expression that yields the argument.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    14 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us