Hacker News new | past | comments | ask | show | jobs | submit login

it doesn't make sense to an imperative programmer because "sequence computations" is like water to a fish. the idea that computation isn't always sequenced doesn't occur to someone who hasn't encountered functional programming.



Not sure what you mean by that. Threaded and event-driven systems don’t necessarily have a predictable sequence. Same with data flow through any non-trivial web application using background processing.

I’ve worked on systems that run through a chain of background workers. Each job had a complete list of operations (one per worker) to preform. When each worker finished, it posted the job back to the general queue with the new state and one less operation to preform.

All programs are eventually sequenced. You can’t work on data that doesn’t exist yet.

I’m pretty sure I don’t lack the ability to understand what your talking about. I am sure I don’t know what the words you are using mean.


As an educator, I get to see many young programmers learn about functional programming usually around their sophomore year of college. They've never used threaded, event-driven, dataflow, or similar systems. All they know how to write are single-threaded Java programs, and their perception is that programs are "a list of statements that tell a computer what to do, in order".

They are especially uneasy about the concept of lazy evaluation. It goes against everything they know about programming - that you write a line of code, it's executed, and you move on to the next line of code. With lazy evaluation (as in Haskell) it's an uphill battle getting them comfortable with the idea of writing a line of code that will be executed at some unspecified point in the future. For many students, this can be a mind-bending realization.


It's just something to know, nobody is actually keeping track of when logic is actually executed.


Let me just explain to you what functional programming is at a high level and I'll get a little bit into the monad. Maybe that will help you understand.

IF you can compress all your javascript into one line of code or as close to it as much as possible then you are absolutely doing functional programming.

That is essentially what functional programming is, how to program so everything goes on one line. You can think of it as expression based programming, or how to compress your entire program into a single expression!

Now, when you see multiline functional code, what's actually happening is that the programmer is giving parts of his expression a name and placing it on another line so that the code is more readable or the programmer could be generalizing logic in the expression for reuse in other places. Example:

    addOneTime8PlusTwoMinusThreeTimes300 = (x) => (x + 1 * 8) + 2 - 3 * 300
is made into

    addOneTimes8 = function(x) => x + 1 * 8
    plusTwoMinusThreeTimes300 = function(x) => 2 - 3 * 300

    addOneTime8PlusTwoMinusThreeTimes300 = (x) => plusTwoMinusThreeTimes300(addOneTimes8(x))
That's it! Turns out that doing this type of organization is EXACTLY the same as doing procedural programming with one extra property! Keeping everything immutable! So if you program in javascript and you keep everything immutable you are doing the exact same thing as compressing all your code onto a single line!

Now that being said there's a lot of this going on in functional programming:

   addOneTime8PlusTwoMinusThreeTimes300 = function(x) => Times300(MinusThree(PlusTwo(Times8(addOne(x)))))
and to make things more easier to read people have special syntax to write it like this:

   addOneTime8PlusTwoMinusThreeTimes300 = function(x) => ( addOne | Times8 | PlusTwo | MinusThree )(x)
The above is literally the same thing as operator overloading you just define the operator to be:

   f | y = function(x) => f(y(x))
and you use it as such:

   ( f | a | b | x )(x)
like bash kinda.

This type of thing is called function composition!

A monad is just a special type of composition Not only do I want to compose all the functions but at each step of the composition I want to do an extra thing! So let's say I want to log the output

So I define

   f | y = (x) => {
       result = y(x)
       print(result)
       return f(result)
   }
Then when I compose:

    ( f | a | b | x )(x)
It will print out each intermediary value along the pipeline!

That is essentially one type of monad. A monad is a way to compose functions such that they do an extra thing! And this intuition probably takes you 85% of the way there on how to use monads in haskell. Monads in haskell just have some extra rules but the intuition is 100% the same thing.

Now you will note that I cheated for f | y. I wrote the code on multiple lines! That is exactly what "sequential" code is!

It is the fundamental property of reality that is at odds with functional programming. Haskell is trying to get rid code that requires you to write things on multiple lines! It is trying to abstract all of that away with a bunch of crazy abstractions so all your code can fit beautifully onto a single line! It is in fact impossible to write the multi line code I wrote above in haskell. What haskell does is present to you the IO monad as an API so you print things through composition and you never have to write "sequential" lines of code.

Turns out when you do single line coding a whole class of errors disappears and your code is also far more modular. It's hard to convince you of the benefits with just words. If you want to know more, you have to walk the path, I can only show you the way.

One more thing. When code is written this way the compiler can do much more tricks with it. Because state is immutable the compiler can execute code in a different order to achieve the same result as your intention. You don't have to often think about this when programming in haskell but it does allow you to do certain tricks.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: