views:

1165

answers:

8

In my second year of University we were "taught" Haskell, I know almost nothing about it and even less about functional programming.

What is functional programming, why and/xor where would I want to use it instead of non-functional programming and am I correct in thinking that C is a non-functional programming language?

Related topics
What’s a good beginning text on functional programming?

A: 

Try the stuff surrounding F#.

IainMH
+5  A: 

May be worth checking out this article on F# "101" on CoDe Mag recently posted.

Also, Dustin Campbell has a great blog where he has posted many articles on his adventures on getting up to speed with F#..

I hope you find these useful :)

EDIT:

Also, just to add, my understanding of functional programming is that everything is a function, or parameters to a function, rather than instances/stateful objects.. But I could be wrong F# is something I am dying to get in to but just dont have the time! :)

Rob Cooper
+3  A: 

Yes you are correct in thinking that C is a non-functional language. C is a procedural language.

robintw
+19  A: 

One key feature in a functional language is the concept of first-class functions. The idea is that you can pass functions as parameters to other functions and return them as values.

Functional programming involves writing code that does not change state. The primary reason for doing so is so that successive calls to a function will yield the same result. You can write functional code in any language that supports first-class functions, but there are some languages, like Haskell, which do not allow you to change state. In fact, you're not supposed to make any side effects (like printing out text) at all - which sounds like it could be completely useless.

Haskell instead employs a different approach to IO: monads. These are objects that contain the desired IO operation to be executed by your interpreter's toplevel. At any other level they are simply objects in the system.

What advantages does functional programming provide? Functional programming allows coding with fewer potentials for bugs because each component is completely isolated. Also, using recursion and first-class functions allows for simple proofs of correctness which typically mirror the structure of the code.

Kyle Cronin
@Kyle Cronin: "The primary reason for doing so is so that successive calls to a function will yield the same result" `Why do we want successive calls to a function to yield the same result. What is the problem with the way things are in C? I never understood this.`
Lazer
@Lazer There are a few reasons why that's undesirable. First, if a function returns the same result, then you can cache that result and return it if the function is called again. Second, if the function does not return the same result, that means that it's relying on some external state of the program, and as such the function can't be easily precomputed or parallelized.
Kyle Cronin
+4  A: 

I prefer to use functional programming to save myself repeated work, by making a more abstract version and then using that instead. Let me give an example. In Java, I often find myself creating maps to record structures, and thus writing getOrCreate structures.

SomeKindOfRecord<T> getOrCreate(T thing) { 
    if(localMap.contains(t)) { return localMap.get(t); }
    SomeKindOfRecord<T> record = new SomeKindOfRecord<T>(t);
    localMap = localMap.put(t,record);
    return record; 
}

This happens very often. Now, in a functional language I could write

RT<T> getOrCreate(T thing, 
                  Function<RT<T>> thingConstructor, 
                  Map<T,RT<T>> localMap) {
    if(localMap.contains(t)) { return localMap.get(t); }
    RT<T> record = thingConstructor(t);
    localMap = localMap.put(t,record);
    return record; 
}

and I would never have to write a new one of these again, I could inherit it. But I could do one better then inheriting, I could say in the constructor of this thing

getOrCreate = myLib.getOrCreate(*,
                                SomeKindOfRecord<T>.constructor(<T>), 
                                localMap);

(where * is a kind of "leave this parameter open" notation, which is a sort of currying)

and then the local getOrCreate is exactly the same as it would have been if I wrote out the whole thing, in one line, with no inheritance dependencies.

John the Statistician
+3  A: 

In my second year of University we were "taught" Haskell […]

What is functional programming […] and am I correct in thinking that C is a non-functional programming language?

Man, your course must really have sucked. Sorry for being so cynical. Anyway, have a look at these related questions:

Konrad Rudolph
+2  A: 

If you are looking for a good text on F#

Expert F# is co-written by Don Syme. Creator of F#. He worked on generics in .NET specifically so he could create F#.

F# is modeled after OCaml so any OCaml text would help you learn F# as well.

Brian Leahy
+4  A: 

John the Statistician's example code does not show functional programming, because when you're doing functional programming, the key is that the code does NO ASSIGNMENTS ( record = thingConstructor(t) is an assignment), and it has NO SIDE EFFECTS (localMap.put(record) is a statement with a side effect). As a result of these two constraints, everything that a function does is fully captured by its arguments and its return value. Rewriting the Statistician's code the way it would have to look, if you wanted to emulate a functional language using C++:

RT getOrCreate(const T thing, 
                  const Function<RT<T>> thingConstructor, 
                  const Map<T,RT<T>> localMap) {
    return localMap.contains(t) ?
        localMap.get(t) :
        localMap.put(t,thingConstructor(t));
}

As a result of the no side-effects rule, every statement is part of the return value (hence return comes first), and every statement is an expression. In languages that enforce functional programming, the return keyword is implied, and the if statement behaves like C++'s ?: operator.

Also, everything is immutable, so localMap.put has to create a new copy of localMap and return it, instead of modifying the original localMap, the way a normal C++ or Java program would. Depending on the structure of localMap, the copy could re-use pointers into the original, reducing the amount of data that has to be copied.

Some of the advantages of functional programming include the fact that functional programs are shorter, and it is easier to modify a functional program (because there are no hidden global effects to take into account), and it is easier to get the program right in the first place.

However, functional programs tend to run slowly (because of all the copying they have to do), and they don't tend to interact well with other programs, operating system processes, or operating systems, which deal in memory addresses, little-endian blocks of bytes, and other machine-specific, non-functional bits. The degree of noninteroperability tends to be inversely correlated with the degree of functional purity, and the strictness of the type system.

The more popular functional languages have really, really strict type systems. In OCAML, you can't even mix integer and floating-point math, or use the same operators (+ is for adding integers, +. is for adding floats). This can be either an advantage or a disadvantage, depending on how highly you value the ability of a type checker to catch certain kinds of bugs.

Functional languages also tend to have really big runtime environments. Haskell is an exception (GHC executables are almost as small as C programs, both at compile-time and runtime), but SML, Common Lisp, and Scheme programs always require tons of memory.

I disagree, in that functional languages can (and, like Erlang, occasionally do) allow single assignments, which don't have side effects. However, your point about side-effects is well-taken. I am not going to change my code, though, since I think illustrating the advantage of functional features in a hybrid language is more important than a strict purity.
John the Statistician