Is functional programming a subset of imperative programming? - programming-languages

One of the main characteristics of functional programming is the use of side-effectless functions. However, this can be done in an imperative language also. The same is true for recursion and lambda functions (for example C++0x). Therefore I wonder whether imperative programming languages are a superset of functional ones.

I can't really say whether they are subset of one another. What I can tell, though, that (except for really esoteric languages) they are all Turing-complete, which means that in the end they're all equally powerful, but not neccesarily equally expressive.

Generally speaking, no; functional programming is a subset of declarative programming (which includes logic programming languages, like Prolog). Many imperative languages borrow elements from functional programming languages, but simply having lambdas or referentially-transparent functions does not make an imperative language functional; functional programming is about more than just these elements.

It is possible to implement a certain programming paradigm in a language which doesn't support the programming paradigm natively. For example its possible to write Object Oriented Code in C while it is not designed for this purpose.
Functional programming is a well developed programming paradigm of its own and is best learnt through languages like Haskell, LISP etc. And after you have learnt them well, even though you don't use these languages regularly, you may start using those principles in the day to day language you use on regular basis.
Some people may like to Google for Object oriented programming in C

A paradigm is a way of doing things, and there are two main programming paradigms: imperative and declarative. The fact that some languages allow to mix both paradigms doesn't mean that one is included in the other, but that the languages are multi-paradigm.
To clarify it a little bit more, let me continue with your analogy: if Lisp and OCaml (for example) are considered functional languages, and both of them allow imperative style... then should imperative be considered a subset of functional?

Most imperative languages don't have functions as first-order types, whereas most functionald o. (As does C++, via boost::function.)
By first-order type, this meas a value/variable can be of any type, an int, a bool, a function from int->bool. It usually also includes closures or bound values as well, where you have the same function, but some arguments are already filled in.
Those two are what functional programming is mostly about, IMHO.

I think it might be helpful to draw a distinction between paradigm and language.
To me, paradigms represent "ways of thinking" (concepts and abstractions such as functions, objects, recursion), whereas languages offer "ways of doing" (syntax, variables, evaluations).
All true programming languages are equivalent in the sense that they are Turing-complete and able, in theory, to compute any Turing-computable function as well as simulate or be simulated by a universal Turing machine.
The interesting thing is how difficult it is to accomplish certain tasks in certain languages or paradigms, how appropriate the tool is to the task. Even Conway's Game of Life is Turing-complete, but that does not make me want to program with it.
Many languages support a number of paradigms. C++ was designed as an object-oriented extension for C, but it is possible to write purely procedural code in it.
Some languages borrow/acquire features from other languages or paradigms over time (just look at the evolution of Java).
A few languages, like Common Lisp, are impressively multi-paradigm languages. It is possible to write code that is functional, object oriented or procedural in Lisp. Arguably, aspect-orientation is already part of the common lisp object system, and therefore "nothing special". In Lisp, it is easy to extend the language itself to do whatever you need it to do, thus it is sometimes called the "programmable programming language". (I'll point out here that Lisp describes a family of languages of which Common Lisp is only one dialect).
I think it doesn't matter which of the terms, declarative, imperative, functional or procedural, is a subset of which. What matters more is to understand the tools languages you're working with, and how those are different from other tools. Even more important is to understand the different ways of thinking that the paradigms represent, since those are your thought-tools. As with most other things in life, the more you understand, the more effective you become.

One way to look at it (not saying it's the right way 'cos I'm not a lang designer or theorist by any means) is that if the language is essentially converted to something else then that 'something else' must be the superset of the source. So bytecode is necessarily a superset of Java. .NET IL is a superset of C# and of F#. The functional constructs in C# (i.e. LINQ) are thus a subset of the imperative constructs of IL.
Since machine language is imperative, you could take the position that, therefore, all languages are imperative, because they are just abstractions useful for humans that are then boiled away by the compiler to procedural, imperative machine code.

Pattern mapping like
f:: [int] -> int
f [] = 0
f (x:xs) = 1 + f(xs)
is something that is for instance one thing that is not available in imperative languages.
Also constructs like curried functions:
add2 :: int -> int
add2 = (2 +)
is not available in most imperative languages

Yes, functional programming is a subset of imperative programming, but...
Yes, because there is nothing in functional programming that you can't do in imperative programming (syntax differences notwithstanding). You can "do" functional programming in an imperative language.
But...
The things you can't do are the key features of functional programming.
By limiting what you can do,
you make certain mistakes impossible,
you enable features (such as program analysis, simpler concurrency, simpler testing, etc).
Other benefits of functional programming are more subjective.
You often hear these arguments.
State allows side effects. Side effects are bad. Functional programming has no state. You can't have side effects without state.
This is a dubious benefit.
First, only unintended side effects are bad. Proper programming practices, such as limiting modification of state to privileged code, alleviate side effect issues.
Second, functional programming only has no internal state. If the program has IO (accessing files, network, hardware) you have external state, thus the potential of side effects.
Functional programs are easier to debug.
In some ways yes, like knowing the explicit path to an exception.
But having state to examine is a debugging benefit that functional programming does not have.
Functional programs are easier to understand.
This is only true if you are fluent in functional programming and not fluent in imperative programming.
I for one, being more fluent in imperative programming, find this argument to be false.

Related

Is Haskell an imperative or declarative paradigm?

I have read some sources where the Haskell's paradigm is described as functional but imperative paradigm. The main source where this is said is Wikipedia. How is possible a functional and imperative paradigm at the same time, or is this a mistake?
Functional languages generally use a declarative methodology when describing their programs, and Haskell is definitely one of these languages; Haskell programs are described as a set of declarations of values (including functions, because functions are first class values).
However, in order for a computer to execute a program, it has to follow a sequence of instructions. To that end, Haskell has a way you can describe what can end up as sequencing when it's executed, in a special syntax (called "do syntax"). Each line of this syntax looks like the next "statement" in a normal imperative language, and kind of behaves that way, too. Really, though, it's just syntactic sugar for ordinary Haskell expressions of function application.
Because it's still written in Haskell, though, and Haskell values and expressions are for the most part typesafe, Haskell is often called "the best imperative language".
As long as changing the order of the atomic parts of a program can change its output, you can safely smack "imperative" on the language. Almost any high-level language is "declarative" in some way, and there are languages that support "declarative programming" better than Haskell does.
In C, for example, enums and even the switch can be "declarative", if you use it in a certain way. Much further in the "declarative" direction is Prolog, and you could write programs in a declarative style, but again, you can also use Prolog to write an imperative program.
Declarative, but there is some caveat to that.
Alonso Church created lambda calculus which Haskell is based on, and Alan Turing created the turing machine. Lambda calculus is purely functions, a turing machine changes the state of a program. Sounds familiar?
Except, it has been shown that these two are equivalent. You can build a turing machine from lambda calculus and vice versa. Which means everything inside Haskell is really just functions, but from them you can build an imperative style of programming.
So yeah, declarative. You don't tell Haskell how to do things, you tell it what a thing is and then build from it.

What does "pure" mean in "pure functional language"?

Haskell has been called a "pure functional language."
What does "pure" mean in this context? What consequences does this have for a programmer?
In a pure functional language, you can't do anything that has a side effect.
A side effect would mean that evaluating an expression changes some internal state that would later cause evaluating the same expression to have a different result. In a pure functional language you can evaluate the same expression as often as you want with the same arguments, and it would always return the same value, because there is no state to change.
For example, a pure functional language cannot have an assignment operator or do input/output, although for practical purposes, even pure functional languages often call impure libraries to do I/O.
"Pure" and "functional" are two separate concepts, although one is not very useful without the other.
A pure expression is idempotent: it can be evaluated any number of times, with identical results each time. This means the expression cannot have any observable side-effects. For example, if a function mutated its arguments, set a variable somewhere, or changed behavior based on something other than its input alone, then that function call is not pure.
A functional programming language is one in which functions are first-class. In other words, you can manipulate functions with exactly the same ease with which you can manipulate all other first-class values. For example, being able to use a "function returning bool" as a "data structure representing a set" would be easy in a functional programming language.
Programming in functional programming languages is often done in a mostly-pure style, and it is difficult to be strictly pure without higher-order function manipulation enabled by functional programming languages.
Haskell is a functional programming language, in which (almost) all expressions are pure; thus, Haskell is a purely functional programming language.
A pure function is one which has no side effects — it takes a value in and gives a value back. There's no global state that functions modify. A pure functional language is one which forces functions to be pure. Purity has a number of interesting consequences, such as the fact that evaluation can be lazy — since a function call has no purpose but to return a value, then you don't need to actually execute the function if you aren't going to use its value. Thanks to this, things like recursive functions on infinite lists are common in Haskell.
Another consequence is that it doesn't matter in what order functions are evaluated — since they can't affect each other, you can do them in any order that's convenient. This means that some of the problems posed by parallel programming simply don't exist, since there isn't a "wrong" or "right" order for functions to execute.
Strictly speaking, a pure functional language is a functional language (i.e. a language where functions are first-class values) where expressions have no side effects. The term “purely functional language” is synonymous.
By this definition, Haskell is not a pure functional language. Any language in which you can write programs that display their result, read and write files, have a GUI, and so on, is not purely functional. Thus no general purpose programming language is purely functional (but there are useful domain-specific purely functional languages: they can typically be seen as embedded languages in some way).
There is a useful relaxed sense in which languages like Haskell and Erlang can be considered purely functional, but languages like ML and Scheme cannot. A language can be considered purely functional if there is a reasonably large, useful and well-characterised subset where side effects are impossible. For example, in Haskell, all programs whose type is not built from IO or other effect-denoting monad are side-effect-free. In Erlang, all programs that don't use IO-inducing libraries or concurrency features are side-effect-free (this is more of a stretch than the Haskell case). Conversely, in ML or Scheme, a side effect can be buried in any function.
By this perspective, the purely functional subset of Haskell can be seen as the embedded language to deal with the behavior inside each monad (of course this is an odd perspective, as almost all the computation is happening in this “embedded” subset), and the purely functional subset of Erlang can be seen as the embedded language do deal with local behavior.
Graham Hutton has a slightly different, and quite interesting, perspective on the topic of purely functional languages:
Sometimes, the term “purely functional” is also used in a broader sense to mean languages that might incorporate computational effects, but without altering the notion of ‘function’ (as evidenced by the fact that the essential properties of functions are preserved.) Typically, the evaluation of an expression can yield a ‘task’, which is then executed separately to cause computational effects. The evaluation and execution phases are separated in such a way that the evaluation phase does not compromise the standard properties of expressions and functions. The input/output mechanisms of Haskell, for example, are of this kind.
I.e. in Haskell, a function has the type a -> b and can't have side effects. An expression of type IO (a -> b) can have side effects, but it's not a function. Thus in Haskell functions must be pure, hence Haskell is purely functional.
As there cannot be any side effects in pure functional code, testing gets much easier as there is no external state to check or verify. Also, because of this, extending code may become easier.
I lost count of the number of times I had trouble with non-obvious side effects when extending/fixing (or trying to fix) code.
As others have mentioned, the term "pure" in "pure functional programming language" refers to the lack of observable side-effects. For me, this leads straight to the question:
What is a side-effect?
I have seen side-effects explained both as
something that a function does other than simply compute its result
something that can affect the result of a function other than the inputs to the function.
If the first definition is the correct one, then any function that does I/O (e.g. writing to a file) cannot be said to be a "pure" function. Whereas Haskell programs can call functions which cause I/O to be performed, it would seem that Haskell is not a pure functional programming language (as it is claimed to be) according to this definition.
For this and other reasons, I think the second definition is the more useful one. According to the second definition, Haskell can still claim to be a completely pure functional programming language because functions that cause I/O to be performed compute results based only on function inputs. How Haskell reconciles these seemingly conflicting requirements is quite interesting, I think, but I'll resist the temptation to stray any further from answering the actual question.
Amr Sabry wrote a paper about what a pure functional language is. Haskell is by this definition considered pure, if we ignore things like unsafePerformIO. Using this definition also makes ML and Erlang impure. There are subsets of most languages that qualify as pure, but personally I don't think it's very useful to talk about C being a pure language.
Higher-orderness is orthogonal to purity, you can design a pure first-order functional language.

What are the different programming language concepts and which languages show them in a pure way

I am no language expert but I'm recently into languages and trying to get an overview of major concepts and "their" languages. This is similar to another question about books. So first, what are the major programming language concepts, e.g.
structured
procedural
object orientated
object orientated - prototype based (e.g. Java Script)
functional (e.g. Haskell)
logic orientated (e.g. Prolog)
meta (if a pure concept of it's own?)
stack based (e.g. Forth)
math based/array oriented (e.g. APL)
declarative
concatenative (e.g. PostScript)
(definitely incomplete list...)
and second to get a good crasp of these concepts, what would be the programming language that's based on/implementing its core concept most naturally and pure?
For example Java is OO, but it's not a good example because it's not pure OO due to atoms.
Lisp is a known to be a functional language, but it's multi-paradigm, so it's not pure. But Lisp may be a pure implementation of "list-based" (if it counts as concept).
Is there a language that's structured (no GOTO) but not procedural? (Maybe XSLT v1.x)
The term you're looking for here is "programming paradigm" and there are a whole lot of them out there. You can get a list of languages which support each from that Wikipedia page and its follow-up links.
For "pure" renditions of any of these, that's harder because it depends on what level of purity you're looking for.
For pure structured (under any sufficiently-loose definition of "pure" here) you can look, for instance, at Modula-2.
For pure object-orientation you're looking primarily at Smalltalk and its ilk if you want absolutely everything to be uniformly treated (not actually necessary under the most common definitions!) or you're looking at languages like Java and Eiffel if you'll accept primitive types under that heading.
For functional you're looking most likely at Haskell.
For logic programming the archetypical language is Prolog, but it's not really pure. The only (mostly-)pure logic language I know of is Mercury, and that only if you view its functional chunks as being essentially compatible with its logical chunks.
...and so on and so on. You get the idea.
I think Pascal is the canonical procedural language.
I also think Lisp (ironically not ML) is the canonical "meta" language.
For one, a macro is a program fragment which modifies a data structure that represents a program fragment---so you use the language to tweak the language. Secondly, it's considered common practice to write self-hosting interpretors, traditionally called metacircular evaluators: they are programs which programs and run them.
Of course, any other language can do that. In Python you have access to the python compiler, and PyPy is a python implementation in python. But Lisp has, I think, the strongest tradition of doing this.
But I'm a Lisp outsider, so what do I know... 'hope-this-helps ;-)
Thanks to JUST MY correct OPINION's answer I was pointed in the right direction. I will give the list of paradigms together with their pure languages as far as I found out till now:
imperative
non-structured --- early BASIC, Assembly
structured --- ?
procedural --- ?
modular --- Modula-2, maybe Pascal
object-oriented
class-based --- Smalltalk
prototype-based --- Self, maybe Java Script, Lua
declarative --- SQL, Regular Expressions, CSS
logic --- Mercury, maybe Prolog
functional --- Scheme, Haskell
tacit/point-free
concatenative --- Joy, Cat
On a different "axis" we have
scalar --- most of them
array --- APL
Don't know where to put it:
stack based --- Forth, Postscript

What technique in functional programming is difficult to learn but useful afterwards?

This question is of course inspired by Monads in Haskell.
wrapping my head around continuation passing style has helped my javascript coding a lot
I would say First-class functions.
In computer science, a programming
language is said to support
first-class functions (or function
literals) if it treats functions as
first-class objects. Specifically,
this means that the language supports
constructing new functions during the
execution of a program, storing them
in data structures, passing them as
arguments to other functions, and
returning them as the values of other
functions. This concept doesn't cover
any means external to the language and
program (metaprogramming), such as
invoking a compiler or an eval
function to create a new function.
Do you want to measure the usefulness in connection with functional-programming itself or programming in general?
In general, the positive experience of functional programming doesn't result from particular techniques but from the way it changes your thinking -
Holding immutable data
Formulating declaratively (recursion, pattern-matching)
Treating functions as data
So I'd say that functional programming is the answer to your question itself.
But to give a more specific answer too, I'd vote for functional abstraction mechanisms like
monads
arrows
continuation-passing-style
zippers
higher-order-functions
generics + typeclasses.
As already said, they are very abstract things on the first view, but once you have understood them, they are extremely cool and valueable techniques to write concise, error-safe and last but not least highly reusable code.
Compare the following (Pseudocode):
// Concrete
def sumList(Data : List[Int]) = ...
// Generic
def sumGeneric[C : Collection[T], T : Num](Data : C) = ...
The latter might be somewhat unintuitive compared with the first definition, but it allows you to work with any collection and numeric type in general!
All in all, many modern (mainstream) languages have discovered such benefits and introduced very functional features like lambda functios or Linq. Having understood these techniques will also improve writing code in this languages.
One from the "advanced" department: Programming with phantom types (sometimes also called indexed types). It's admittedly not a "standard" technique in functional programming but not entirely esoteric either, and it's something to keep your brain busy for awhile (you asked for something difficult, right? ;)).
In a nutshell, it is about parameterizing types to encode and statically enforce certain properties at compile time. One of the standard examples is the vector addition function that statically ensures that given two vectors of length N and M will return a vector of length N+M or otherwise you get a compile-time error. Yes, there are more interesting applications.
These techniques are not quite as useful in C++ as they are in a proper functional programming language, but so far I've managed to sneak some of this stuff in all of my recent projects at work to a varying degree, most recently in a C++ EDSL context where it worked out really well. You don't necessarily have to encode fancy stuff, learning this helped me catching the situations where a few type tags can reduce the verbosity of an EDSL or allowed a cleaner syntax, for example.
Admittedly, the usefulness is somewhat restricted by language support and what you're trying to achieve.
Some starters:
Generic and Indexed Type (slides with some brief applications overview)
Fun with Phantom Types
The Kennedy and Russo paper mentioned in the slides is Generalized Algebraic Data Types
and Object Oriented Programming and puts some of this stuff into the context of C#/Java.
Chapter 3 in Dave Abraham's book C++ Template Metaprogramming is available online as sample chapter and uses these techniques in C++ for dimensional analysis.
A practical FP project using phantom types is HaskellDB.
I would say that Structural typing in OCaml is particularly rewarding.
recursion. Difficult to wrap your head around it at times
The concept of higher-order functions, lambda functions and the power of generic algorithms that are easy to combine were very beneficial for me. I'm always excited when I see what I can do with a fold in haskell.
Likewise my programming in C# has changed a lot (to the better, I hope) since I got into functional programming (haskell specifically).

What functional language techniques can be used in imperative languages?

Which techniques or paradigms normally associated with functional languages can productively be used in imperative languages as well?
e.g.:
Recursion can be problematic in languages without tail-call optimization, limiting its use to a narrow set of cases, so that's of limited usefulness
Map and filter have found their way into non-functional languages, even though they have a functional sort of feel to them
I happen to really like not having to worry about state in functional languages. If I were particularly stubborn I might write C programs without modifying variables, only encapsulating my state in variables passed to functions and in values returned from functions.
Even though functions aren't first class values, I can wrap one in an object in Java say, and pass that into another method. Like Functional programming, just less fun.
So, for veterans of functional programming, when you program in imperative languages, what ideas from FP have you applied successfully?
Pretty nearly all of them?
If you understand functional languages, you can write imperative programs that are "informed" by a functional style. That will lead you away from side effects, and toward programs in which reading the program text at any particular point is sufficient to let you really know what the meaning of the program is at that point.
Back at the Dawn of Time we used to worry about "coupling" and "cohesion". Learning an FP will lead you to write systems with optimal (minimal) coupling, and high cohesion.
Here are things that get in the way of doing FP in a non-FP language:
If the language doesn't support lambda/closures, and doesn't have any syntactic sugar to easily mostly hack it, you are dead in the water. You don't call map/filter without closures.
If the language is statically-typed and doesn't support generics, you are dead in the water. All the good FP stuff uses genericity.
If the language doesn't support tail-recursion, you are hindered. You can write implementations of e.g. 'map' iteratively; also often your data may not be too large and recursion will be ok.
If the language does not support algebraic data types and pattern-matching, you will be mildly hindered. It's just annoying not to have them once you've tasted them.
If the language cannot express type classes, well, oh well... you'll get by, but darn if that's not just the awesomest feature ever, but Haskell is the only remotely popular language with good support.
Not having first-class functions really puts a damper on writing functional programs, but there are a few things that you can do that don't require them. The first is to eschew mutable state - try to have most or all of your classes return new objects that represent the modified state instead of making the change internally. As an example, if you were writing a linked list with an add operation, you would want to return the new linked list from add as opposed to modifying the object.
While this may make your programs less efficient (due to the increased number of objects being created and destroyed) you will gain the ability to more easily debug the program because the state and operation of the objects becomes more predictable, not to mention the ability to nest function calls more deeply because they have state inputs and outputs.
I've successfully used higher-order functions a lot, especially the kind that are passed in rather than the kind that are returned. The kind that are returned can be a bit tedious but can be simulated.
All sorts of applicative data structures and recursive functions work well in imperative languages.
The things I miss the most:
Almost no imperative languages guarantee to optimize every tail call.
I know of no imperative language that supports case analysis by pattern matching.

Resources