6 ms·
From Imperative to Functional: how to make the leap
- russellallen 14y agoWe used to see these articles for object orientation. Now we see them for functional. I look forward with bated breath for the next paradigm!
- pjmlp 14y agoActually you could already start to see that with multi-paradigm languages.
- friendly_chap 14y ago"Your program isn't about what it does, but about what things are" "In the Haskell code, the data flows from right to left, instead of from top to bottom" I find this article vague, imprecise, forced. It's like those "lets do OOP for the sake of doing OOP" articles, just swap OOP to functional programming.
- loup-vaillant 14y agoThe statements you cite are trivial, but I believe they are quite precise. Can you tell me more about how my article spurs a feeling of vagueness? I might be able to fix it. Also, I didn't mean to advocate FP, at least not there. I have written it for the poor C++/Java programmer who is forced to decipher an OCaml script written by a jerk who since left the company. (Disclaimer: I would be the jerk.)
- friendly_chap 14y ago> Can you tell me more about how my article spurs a feeling of vagueness? Not just you, approx. 90% of the software industry suffers from it (big IMHO here of course). I think too much emphasis is placed on paradigms and magic approaches, instead of talking about things are. Something like this: "Is C++ a big pile of mess? Yes. Is Haskell a much better designed language, even if its implementations are slower because the higher level of abstraction clashes with the underlying hardware currently in use? Yep." Also, what you are trying to describe with all those top-bottom-left-right and similar analogies is the fact that in FP languages you mostly work with expressions, while the building blocks of imperative languages are statements. I don't really have the time to continue here maybe I will write a blog post myself too :).
- brokenparser 14y agoThis article did it for me, it was originally written in 1989: http://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf http://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pd...
- cust_support 14y agoPlease stop using square or sqrt or recur/iter as examples of functional programming. It's as bad as every "Hello World" println from new imperative languages that seem to pop up everyday. And please stop suggesting that imperative programmers are unable or unwilling to fully grasp the functional mindset. It's really unnecessary. This is akin to every claim that new technology is "scary". Disruption is not frightening, it's just unwelcome. Give the imperative programmers a little slack; they're trying to solve problems just like everyone else. It's not their fault you don't enjoy reading epic poems written in iambic pentameter.
- preavy 14y agoI have a possible correction. Might dbl-all not be better named sqr-all? Thanks for the article by the way.
- friendly_chap 14y agoGood catch!
- grapjas 14y agoWhy do you use 'λ' instead of '\'? Is this normal in haskell projects?
- dkhenry 14y agoEither the author has a shiny new keyboard with a λ key, or they really really like to copy and paste.
- loup-vaillant 14y agoShiny new keyboard: http://bepo.fr/ http://bepo.fr/
- friendly_chap 14y agoSyntax error: Either data constructor not in scope. Perhaps you meant one of these: Left "the author has a shiny new keyboard with a λ key" Right "they really really like to copy and paste"
- gruseom 14y agoOr a programmable text editor. I bind λ to S-l in emacs.
- loup-vaillant 14y agoAs far as I know, it isn't. I just figured that anyone who understand '\' might understand 'λ' as well. And those who don't know Haskell might just figure that 'λ' stands for 'function'.
- anonymouz 14y agoBut in that way your Haskell code examples seem to not be valid Haskell anymore. Seems to be a rather pointless change for the sake of simply breaking things.
- loup-vaillant 14y agoWell, given this: http://news.ycombinator.com/item?id=5278883 http://news.ycombinator.com/item?id=5278883 I now believe the notation needs to be explained anyway. I'll switch back to '\'.
- rosche 14y agoAgain! I've been hearing the "switch to functional!" spiel since the 70s (being honest, since sometime in the 60s, but I digress)... stop it already! Hasn't happened in 40 years, won't happen now.
- friendly_chap 14y agoDude, why are you so impatient?
- tikhonj 14y agoIt's not like everyone is going to switch, but some people--especially on HN--might, so it's definitely worth reading about. I certainly know some startups considering functional programming, largely because so many people seem to like it. Also, if you look at other popular technology like OOP, they were pushed even harder than functional programming. When I was initially learning programming, I read a ton of books and articles all advocating it. Similarly, I've seen more people advocating Python than Haskell, and that worked too. So maybe it's not enough by itself to make seething popular, but it seems necessary or at least very helpful. There's certainly no reason to stop trying!
- nkurz 14y agoHi L-V, I'm a C programmer, and I've gone through the article a couple times without enlightenment. This isn't necessarily the fault of the article, but thought I'd offer the places I couldn't follow. Perhaps they will be useful for understanding a beginners viewpoint. *int square(int n) │ square :: Int -> Int* Would be great if you offered an example where the argument and return type differed. As is, I don't know which order the Haskell declaration uses. Now it is possible to write the Haskell program that will naturally read from left to write If this is essential at this point, it should be fleshed out more. Otherwise it feels like a distracting aside and out of place in a short introduction. -- before │ -- after compute n = baz (bar (foo n)) │ wiz n = bar (foo n) │ compute n = baz (wiz n) This seems perfectly clear, which makes me suspect the other parts are intended to be simple as well. (.) :: (b -> c) -> (a -> b) -> (a -> c) Not clear why the left side is (.). Is this because it's non-alpha? Because it's infix? Something else? Order to read right hand side still unclear. Also don't know if reuse of a, b, and c as variables is significant. g . f = λx -> g (f x) Can't quite follow, but this might be because I'm not sure if the λ is syntactically important, or just a naming convention. be expressed literally (see 1 vs λx -> g (f x)); I can't figure out what this means, possibly because I'm not sure what 'literally' means in this context. Also wasn't clear at first that "1" was meant as a number (or is that an 'L'), not a footnote or reference. -- A List is either data List a = Empty -- an empty node, | Cons a (List a) -- or a cons cell Would help to define a "cons cell". Is Cons a data type or a function here? Is there a standard for capitalization? Not clear to me how the 'a' on the left side relates to the two on the right. Is 'data' a keyword, a type, or something else? inc-all l = map (λe -> e + 1) l Throughout this whole section, I had no idea which characters were one's and which were L's. I ended up cutting and pasting into emacs and capitalizing. Perhaps something other than 'l' for the placeholder variable? Or it is more than a placeholder? The concept seemed straightforward, but the example was very hard to figure out. It is not obvious from the syntax, but Haskell functions only have one argument. Would help to mention this before the (.) example. Multiple arguments are emulated by returning functions. So I guess this means the argument is on the left of the first '->' and the return type is to the right? And how should '->' be pronounced when spoken? inc-all (Cons e l) = Cons (foo e + 1) (inc-all l) I'm guessing 'e' is 'element', and lower-case 'L' is list. Why/when did we switch from 'a' in the definition of List? And where did 'foo' come from? Is this a builtin function? A user defined function? map (a -> b) -> List a -> list b Is the lower case for the last 'list' important? For that matter, is case important at all in Haskell? Also, are the types on the left for 'a' and 'b' defined by the given types on the right? Also haven't figured out why this declaration(?) has no '::' as the others do. dbl-all (Cons e l) = Cons (foo e * e) (inc-all l) Is that supposed be 'dbl-all' at the end? And should that be "2 * e" instead of "e * e"? I'm hoping these are typos, otherwise I'm understanding even less than I thought. Note that the first argument is a function, hence the (a -> b) between parentheses. Great! Confirmation on how to read the function declarations. Now back to reread the first half of the article again. Hopefully this means the return type is after the last '->'? Very simple, but without the fundamentals I just gave, one hardly stands a chance at deciphering it. Unfortunately, I still don't feel confident in my ability to decipher now that I have have the been given those fundamentals. I think a gloss of what 'λe' actually means would help. As a type, is it parallel to "void * (* e)( void * )" in C? Despite this long list, I appreciate that you wrote the article. Much better to have something possibly flawed than nothing at all. Maybe one day I'll actually understand it!
- mindbat 14y ago"Your program isn't about what it does, but about what things are" This is exactly backwards. OOP programming is about what things are. As Steve Yegge put it, functional programming is about verbs, about what your program does to the data passing through it. Steve's original post, "Execution in the Kingdom of Nouns," is much clearer: http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom... "Your code isn't just a linear sequence of instructions, but a tree of nested expressions." This is also off the mark. If you're working in a Lisp, sure, you're directly manipulating abstract syntax trees. But this is a mark of a homoiconic language, not a functional one. "Functions are ordinary mathematical objects, just like an integer is." Also wrong. In a functional language, functions are first-class objects, meaning they have an existence independent of classes. But they're something different from integers, which are usually defined as primitives in the language.
- loup-vaillant 14y agoVerb vs nouns. Well, what are objects in OO? They're things that do this, and change that… This is a lot about what objects do, and what we do to them. On the other hand, in FP, one "does" only one thing: create new values. There is a lot of verbs in FP, but they don't do anything… Anyway, I guess I'll need to review that. Instruction sequence vs Expression tree It's jot just Lisp. Ocaml and Haskell apply as well. We don't manipulate the syntax tree, but it doesn't mean it isn't there. For instance, the following is a valid Ocaml or Haskell expression: if condition then foo else bar (if condition2 then baz else wiz) This is not unusual code. Here is the C equivalent: condition ? foo : bar(condition2 ? baz : wiz) This is a tree of nested expressions. Functions as ordinary mathematical objects. I'm just saying that functions belong to the bucket of mathematical objects. As are integers. And sets. And lists… "First class" just mean we treat them as such. From https://en.wikipedia.org/wiki/First-class_function https://en.wikipedia.org/wiki/First-class_function > In languages with first-class functions, the names of functions do not have any special status; they are treated like ordinary variables with a function type.
- mindbat 14y ago