Live data from Hacker News

Functional Programming For The Rest of Us

defmacro.org

51–60 of 69 posts

Re: Functional Programming For The Rest of Us

#51
post #7

Earlier quoted context omitted.

I think the "if it compiles, it works" has to do with Haskell's type system being much more expressive than most static languages, and that most of your code will be declarative and pure. Purity helps because your program will necessarily be composed of small, self-contained modules (usually functions) that have no implicit dependencies. The type system helps because you can encode a lot of the code's intent in type…

Agreed; after getting used to working with Haskell's type system, I've found it kind of painful to use languages with weaker, less expressive type systems (which unfortunately, is basically every practical language other than Haskell). The ability to transform all manner of bugs into compile-time errors via the typechecker is indispensable. Once you start digging into GHC extensions like GADTs and type families, it g…

When I know what I'm programming, I agree, but I tend to find strong static type systems get in my way for exploratory programming. If I'm trying out some music-synthesis idea, for example, the #1 thing I want is to hear some sound ASAP, even if the code only runs for certain choices of parameters and crashes after 30 seconds. Then, I'll fix it later if it sounds promising.

I find that in Lisp, for example, I'm able to do partial, tentative refactorings, where I sort-of change something as an experiment, just enough that it works in one example case, but don't completely refactor everything to be consistent with the change yet, because I'm not sure if I really want the change or not. That kind of thing is really hard to push through in languages that care more about static types, and I often find myself thinking something along the lines of: yes I know that function there isn't updated with the new type signature, but I'm only planning to try this out initially with one choice of parameters, and I know that in that case the function isn't even called, so please just run the damn program!

Re: Functional Programming For The Rest of Us

#52

Earlier quoted context omitted.

Agreed; after getting used to working with Haskell's type system, I've found it kind of painful to use languages with weaker, less expressive type systems (which unfortunately, is basically every practical language other than Haskell). The ability to transform all manner of bugs into compile-time errors via the typechecker is indispensable. Once you start digging into GHC extensions like GADTs and type families, it g…

When I know what I'm programming, I agree, but I tend to find strong static type systems get in my way for exploratory programming. If I'm trying out some music-synthesis idea, for example, the #1 thing I want is to hear some sound ASAP, even if the code only runs for certain choices of parameters and crashes after 30 seconds. Then, I'll fix it later if it sounds promising. I find that in Lisp, for example, I'm able…

When this happens to me (using haskell), I just quickly do:

   otherfunc = undefined
   otherfuncReal :: ...
   otherfuncReal = ...
The best exploratory programming I've seen in haskell also does this for types to some extent; you know you're writing music, so you start with something like:

   data Music -- stubbed in data type with no constructor
Then maybe you decide it involves a series of notes with duration, so you change it:

   data Music = [(Note, Duration)]
   data Note -- stub
   type Duration = Int

Re: Functional Programming For The Rest of Us

#53
post #33

Is it me or that "A Walk in the Park" sounds like Sheldon Cooper from the Big Bang theory: "Fire up the time machine. Our walk in the park took place more than two thousand years ago, on a beautiful sunny day of a long forgotten spring in 380 B.C. Outside the city walls of Athens, under the pleasant shade of olive trees Plato was walking towards the Academy with a beautiful slave boy. The weather was lovely, the dinn…

Other way around, I believe. The date on this article is 2006, BBT started late 2007.

Re: Functional Programming For The Rest of Us

#54

After racking my brain for years trying to figure out why shitty "design patterns" have been winning while functional programming (despite its superiority to typical object-obfuscated architecture) remains on the back-burner, I've come to a few conclusions. 1. The name "functional programming" doesn't sell us; it just sounds impractical. What we do isn't really "functional programming" in a purist sense. We need side…

Scala is actually less complex than Java by far.

I'm sorry, but I can't let this one go by. I can accept the argument that FP may be less complex once you get used to it (not sure I agree but let's go with it) and immutability by default is great but just because Scala and/or it's surrounding community allow or encourage this style doesn't mean that Scala-the-language is less complex than Java-the-language. That's a statement bordering on the absurd - I would say that Scala is demonstrably massively more complex than Java. Many of the things that make Scala great are extremely complicated, both theoretically and practically. That doesn't stop it being great but it does make it complex.

Re: Functional Programming For The Rest of Us

#55

Good article , cleared a few things up for me. One thing I am still a bit hazy on though. He mentions that continuations could be used in the context of a web app to maintain state between HTTP requests. I'm not quite clear how this would actually work. Lets say you have something like this (in psuedocode): Let's say we have a counter we want to increment on each request. doHTTPRequest(requestVars) { renderPage(reque…

Node.js is built around a lot of continuations, if I recall. It's very common in event driven computing. I believe the basic way to do it is that the function that processes the original request both returns the output and the continuation, then the next time the user connects it would use the continuation instead of the original function. function doHTTPRequest(requestVars, renderPage) { (content, renderNextPage) =…

What you're describing is CPS, but that's not how continuations would typically be used in a webapp, it's actually a compiler technique (I've always thought it was crazy that node.js forces you to do by hand something that should be done by the compiler). A language that supports full continuations as first class objects, for example some Scheme implementations, allow you to actually suspend the current execution (including the entire call stack) and store it somewhere, and then start executing it again at a later point in time. So your web container can start running a thread of execution for a particular request, suspend it after it writes its response then resume it again when it receives the next request corresponding to this web session. It allows you to write code like:

    function handleSession() {
      renderFormPage()   // writes response with HTML for form
      suspend()          // wait for next request in the session
      processForm()      // process the form data - notice this is the same function
    }
It's a very powerful technique and can make web programming very intuitive since you can have a single linear flow for a complex web interaction.

Check out Chris Double's tutorial on this:

http://double.co.nz/scheme/modal-web-server.html

Or SISC-Web for a simple but complete implementation:

http://siscweb.sourceforge.net/overview.html

Re: Functional Programming For The Rest of Us

#56
post #48
post #43

Earlier quoted context omitted.

OK - I checked wikipedia: In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. Sounds exactly what I was thinking - map is not mathematical function - because it can interact with the global state (you can apply map twice to the same data and get different results - for example if in the function yo…

This is a single introductory sentence. You should not reason that far with it. With that reasoning you could claim addition is impure, because time() + 1 changes over time. map is definitely a pure function. If you apply it to impure arguments, of course the result will be impure. The point in FP is to avoid using 'time', not 'map'.

That's a good argument - but it does not really resolve the definition problem. It seems that some people think that 'functional programming' means 'programming with mathematical functions' - while others think that it means 'programming with first-class functions'. I can take this or that definition - but if wikipedia uses one definition - this sounds like a good argument that more people use the 'mathematical functions' definition. I also think that 'mathematical functions' is a more useful definition - because it implies 'referential transparency' and probably other interesting things that are usually quoted as the advantage of using functional programming.

Re: Functional Programming For The Rest of Us

#57
post #43

Earlier quoted context omitted.

OK - I checked wikipedia: In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. Sounds exactly what I was thinking - map is not mathematical function - because it can interact with the global state (you can apply map twice to the same data and get different results - for example if in the function yo…

"map is not mathematical function - because it can interact with the global state (you can apply map twice to the same data and get different results" I don't think I quite understand you. I think when you say "mathematical function" you mean "pure function". And when you say "global state" I assume you mean "impure operations". But (from my understanding) map is purely functional and doesn't do anything impure like…

OK - I can agree with the interpretation that the 'impurity' is not inside map - but rather in the argument it takes. You can reconcile it with the mathematical definition of function by saying that some 'programming functions' take the implicit 'state' argument and that map is not one of them.

It still does not resolve the definition problem - is functional programming programming with pure mathematical functions - or is it using first-class functions (not in mathematical sense)? Which definition is more useful? Which is more widely used?

Re: Functional Programming For The Rest of Us

#58
post #44
post #43

Earlier quoted context omitted.

OK - I checked wikipedia: In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. Sounds exactly what I was thinking - map is not mathematical function - because it can interact with the global state (you can apply map twice to the same data and get different results - for example if in the function yo…

I'm reading this differently than you are; > functional programming is a programming paradigm NOT a programming language. What I think this means is that your usage of map is such that the computation is what matters, not mutating the state. I can do that just as well in Python, JavaScript, OCaml, Scala, Clojure and Haskell. In other languages too, yes, but not nearly as easily (due to lack of closures/complicated fu…

I insist that what is important is how much of the purity you have - because it is a more widely used definition (as supported by my wikipedia quote) and also this is what implies the nice computational properties of the code, and what is not important is if you use first class functions (not in the mathematical sense).

Re: Functional Programming For The Rest of Us

#59
post #34

Earlier quoted context omitted.

Agreed; after getting used to working with Haskell's type system, I've found it kind of painful to use languages with weaker, less expressive type systems (which unfortunately, is basically every practical language other than Haskell). The ability to transform all manner of bugs into compile-time errors via the typechecker is indispensable. Once you start digging into GHC extensions like GADTs and type families, it g…

> which unfortunately, is basically every practical language other than Haskell Is this also true of Ocaml? I have experience in neither, but my understanding from reading up on this says Ocaml and Haskell are roughly equivalent, and if anything - Ocaml is even more expressive. Anyone with real world experience who can comment on this?

It has been proven that you can express certain things with ML-style functors that are difficult or impossible to express with standard Haskell-style type classes. But almost everybody uses GHC and turns on lots of type system extensions in their projects, which is going to make the issue a lot murkier, and on top of that ML-style functors require a bit more finger work and explicitness. Ultimately, it's going to come down to preference.

They're roughly equivalent the way Python and Ruby are roughly equivalent, or Common Lisp and Scheme. From any other linguistic paradigm, yeah, they're extremely close. But from one to the other, it feels like there is a tremendous gulf.

A lot of the benefits tmhedberg is talking about come from I/O being a monad in Haskell and the lack of "assignables," which constrains your ability to mix side-effects and state changes with pure code. Of course, you can defeat it if you really try (MVars and unsafePerformIO) but it's not the kind of thing you would do accidentally. And you could achieve a lot of the same benefits in OCaml by writing monadic standard libraries and never using refs.

So, if by "expressive" you mean the type system allows you to express complex relationships, Haskell is more expressive. But if by "expressive" you mean the language allows you to express calculations in more ways, OCaml is more expressive. In my experience, "expressiveness" is usually a foil for some other attribute and doesn't usually illuminate the debate much.

In the end, they're just tools, albeit with overlapping purposes. OCaml is easier to learn and compiles faster, Haskell raises your confidence in the code and has cooler tricks. Both are fascinating and stunningly better than lots of other options. If I had to choose which one to learn today, I'd look at some example code in both and ask myself which one I want to be staring at for the next six months.

Re: Functional Programming For The Rest of Us

#60

A great read. Just a couple of things that jumped out at me: “In functional languages automatic analysis of functions and finding good candidates for concurrent execution is as trivial as automatic inlining!” It isn’t exactly trivial. If you can evaluate anything concurrently, then you still have to figure out what’s worth the overhead of spinning up a thread to run concurrently. And many operations are inherently se…

Of course benchmarking is essential, but the Control.Parallel library can decouple expressions to run in parallel (called sparks) from threads, and manages the whole shebang for you. You more-or-less say x `pseq` y and it will try to evaluate them in separate threads if possible. The RTS statistics will tell you how many sparks got "converted" to run on another CPU and whatnot, so you can compare and see if you actually got an improvement, but it is a bit easier than spinning up dedicated threads, assuming you're parallelizing pure computations. For true concurrency, you still need to deal with threads.
Post reply on HN