I have been trying to wrap my head around functional programming for a while now? I have looked up lambda calculus, LISP, OCML, F# and even combinatorial logic but the main
Even if you don't use it in your work, learning one or more functional programming languages is a great way to learn to think differently and gives you a toolkit of alternative approaches to problems (it can also frustrate you when you can't do something as neat and clean as a functional approach in other languages).
And it made me a better at writing XSL stylesheets.
The only completely pure functional language I know of is the template system in C++. Haskell takes second place by making the imperative portions of the program explicit.
In Haskell the program has mutable state, but functions (almost always) don't. You keep like 99% percent of program pure, and only the portion that interacts with the outside world is impure. Therefore when you are testing a function, you know there are no side effects. Pure core, with an impure shell.
Functional Programming is about limiting & isolating side-effects, not trying to get entirely rid of them... because you can't.
... and yes I find FP useful (certainly with Erlang anyways): I find it is easier to get from "idea" to "program" (or problem to solution ;)... but of course that could just be me.
You need to know at least another essential concept: Monads. You will need this to do I/O and the other "useful" stuff!
Interacting with a user and communicating with a remote service do require some sort of non-functional part to your software.
Many "functional languages", (like most Lisps) are not purely functional. They still let you do things with side-effects, though side-effecty things are "discouraged" in most contexts.
Haskell is "purely functional" but still lets you do non-functional things via the IO monad. The basic idea is that your purely functional program emits a lazy data structure which is evaluated by a non-functional program (which you don't write, it's part of the environment). One could argue that this data structure itself is an imperative program. So you're sort of doing imperative meta-programming in a functional language.
Ignoring which approach is "better", the goal in both cases is to create a separation between the functional and non-functional parts of your programs, and to limit the size of the non-functional parts as much as possible. The functional parts tend to be more reusable, testable, and easier to reason about.
The way Haskell does it is by using monads see wikipedia and the explanation by Haskell on their page.
Basically the idea is that you do not get rid of the IO monad. My understanding is that you are able to chain functions that unwrap an IO monad and execute that function. But you are not able to remove the IO monad altogether.
Another example using monads that is not directly tied to IO is the Maybe Monad. This monad is 'unwrappable' in contrary to the IO monad. But it is easier to explain the use of monads using the Maybe monad. Let's assume you have the following function.
wrap :: Maybe x -> (x -> y) -> Maybe y
wrap Nothing f = Nothing
wrap (Just x) f = Just (f x)
now you can call wrap (Just 4) (5+)
which will return Just 9
.
The idea of the IO-monad is that you can use functions like (+5) on the internal type. The monad will assure that the functions will be called in serial, because every function is chained with the wrapping IO-monad.