15 ms·
Why functional programming matters
- patrickmn 10y agoWhy compose classes, abstract base classes, etc. when you can compose simple functions! It's true that abstractions in functional languages can seem foreign and hard to understand, but generally they have some purpose, being grounded in mathematical practice. OO abstractions and patterns OTOH, taught essentially in "elementary school" which possibly makes them seem easier to understand, do a very poor job of solving more problems than they create. Learning a functional language is often a transformative experience that lasts throughout a career, whether you even use functional languages or not. It might make you do something as simple as partitioning which functions have side effects and which don't, even if the type system doesn't enforce it. Or use a form of quick/fuzz testing, even if it's not the standard test suite. Or make parts of the data immutable for scalability, auditability, etc. Or... There really are few things as satisfying as developing a large codebase in a functional language. A lot of the frustrating maintenance work just goes away. But even if you don't, functional principles can yield similar benefits in imperative languages.
- mpweiher 10y ago> Why compose classes, abstract base classes, etc. when you can compose simple functions! Because they allow you to compose higher level entities? (Incidentally, one would generally compose objects). "When programming a component, the right computation model for the component is the least expressive model that results in a natural program." -- Concepts Techniques and Models of Computer Programming So when a less expressive model (such as FP) is sufficient for a "natural" program, definitely use that. And of course that has been the general recommendation. Switch to a more expressive model once this is no longer the case. In my experience, FP tends to be good for "computation", at least if performance isn't a primary concern. However, most of what "computers" (badly named) do today isn't computation, and modeling communication and storage over time tend to get awkward (though obviously possible).
- haskellandchill 10y ago> So when a less expressive model (such as FP) You can express object models in FP so what you are saying is very confusing to me.
- mpweiher 10y agoModels in "Concepts Techniques and Models of Computer Programming" Note that they are talking about general models of computation, in particular including at least: - Declarative sequential model (strict functional programming, deterministic logic programming, dataflow/logic variables, higher-order procedures). Component behavior is independent of rest of program. - Declarative concurrent model (explicit threads, by-need/lazy computation, data-driven concurrency, demand-driven concurrency). Almost as simple as declarative sequential. Declarative model with exceptions: allows nondeterminism to be visible. - Message-passing concurrent model (declarative plus ports/communication channels). Allows nondeterminism, and allows nondeterminism to be restricted to particular components. - Stateful model (declarative model extended with explicit state). Allows components to keep history. Typical of sequential OO programming. - Shared-state concurrent model (declarative extended with both explicit state and threads). Typical of concurrent OO programming. - Relational model (declarative extended with search). Search space explored by testing choices until result is satisfactory. Encompasses Prolog-style logic programming. - Constraint programming and still other models are discussed elsewhere in the book. http://wiki.c2.com/?PrincipleOfLeastPower http://wiki.c2.com/?PrincipleOfLeastPower
- louthy 10y ago> Because they allow you to compose higher level entities? That isn't true. FP still uses data records, they're just not tightly coupled to the functionality like OO. Pure functions + immutable types is a more powerful programming paradigm than data and functionality encapsulation via classes and methods. Also more advanced techniques like combinators can encode more complex and extensible patterns in a significantly more robust way than any OO class hierarchy (see 'parser combinators' for an example).
- 10y ago
- dominotw 10y ago>Why compose classes, abstract base classes, etc. when you can compose simple functions! What do you think of the recent rise of 'hybrid' languages like scala?
- js8 10y agoMy opinion is that it's a double-edged sword. It's like when someone recommends you to learn SQL and relational algebras, and you, coming from OOP world, say, oh, I can learn some ORM first, that will make it easier. Personally, I found that diving directly into the language that represents a paradigm in the "pure" form (for FP I would recommend Haskell) works best for me. It makes it most obvious why things are done certain way.
- dagw 10y agoPersonally I think they're great for development, but less great for learning. The advantage with something like Haskell is that it forces you do to things the 'right way' every single time and puts all the functional concepts right at the forefront. Once you've internalized the concepts then you can easily go onto other languages and bring those concepts with you. While I haven't really written anything in Haskell since leaving school, learning Haskell has informed (and in my opinion improved) the way I program in every language more than basically anything else I've done.
- patrickmn 10y agoA great way to get a taste of FP, but as others noted, not the best way to really learn FP (Haskellbook and SICP are great.)
- acdha 10y ago> It's true that abstractions in functional languages can seem foreign and hard to understand, but generally they have some purpose, being grounded in mathematical practice. OO abstractions and patterns OTOH, taught essentially in "elementary school" which possibly makes them seem easier to understand, do a very poor job of solving more problems than they create. This kind of sweeping unsupported assertion is actively harmful for FP evangelists. Anyone who isn't already a fanboy is most likely going to read that and say “clearly this person has no idea what they're talking about. [close tab]”. If you want to make a productive form of this argument it'd be better to focus on discussing why the mathematical abstractions are so much better with comparisons to their actual recommended OOP counterparts. The points you mentioned about things like side effects or immutability are good but you need to not give someone a reason to go away before getting there, especially since there are going to be common tasks like I/O which are _not_ going to look like an improvement for anyone who isn't already on-board.
- patrickmn 10y ago> This kind of sweeping unsupported assertion is actively harmful for FP evangelists. Anyone who isn't already a fanboy is most likely going to read that and say “clearly this person has no idea what they're talking about. [close tab]”. That seems as much an unsupported assertion (i.e. opinion) as what I wrote. I don't think it's useful to try to write a comprehensive essay with no ambiguity every time I comment, and I don't have the time. Doesn't mean I don't believe the things I say. :) If you decide to close the tab because I said functional programming languages are much better at abstraction, that's too bad, but it's not exactly an unsupported assertion--and I'm not trying to sell you anything anyway. If it helps, most of my FOSS stuff is written in Go, a language Haskell fans generally vehemently dislike for "ignoring 30 years of PL research." I actually like Go for a similar reason I like FP: It does away with a lot of the bad abstraction (classes) and emphasizes the good (interfaces.)
- acdha 10y agoThe difference is that you're dismissing the entire field of mainstream software development for the last couple of decades as “elementary school” level abstractions which “do a very poor job of solving more problems than they create”. A strong majority of working programmers are familiar with those concepts because they were taught those concepts in schools, by industry experts, and see them used by platform developers and vendors. FP is not that pervasive and anyone trying to make the case that it's better across the board has to address that familiarity gap. Try to think about, say, the average Java or C# developer working on a large project. They aren't spending their day saying “OOP is terrible” and when you say something is better because it's “grounded in mathematical practice” that's really non-obvious to someone who's thinking the main way their life would improve would be if they could get the business stakeholder to make a decision and stick with it for more than 24 hours, stop using Oracle products, etc. Talking about avoiding shared state and side-effects, going beyond Java-level typing to make refactoring safer, etc. is a lot more useful since those probably are things they spend time on regularly.
- hota_mazi 10y ago> Why compose classes, abstract base classes, etc. when you can compose simple functions! Why only do one while you can do both? Modern languages have first class functions and support class polymorphism and parametricity, which is still a very powerful way to describe problems intuitively.
- humanrebar 10y ago> Why only do one while you can do both? Theoretically you can do both. Practically, few languages give you the tools you'd want to ensure functional purity. C++ is a multi-paradigm language, for instance. But it doesn't have any concept of immutable data. The 'const' keyword exists but it only does a very shallow check for immutability (i.e., the pointer won't change but its data might). And even with a 'const', there are still huge backdoors (the 'mutable' keyword). Point being, it's possible, but you'd be relying on convention in your design and care in your implementation to make it work.
- mpfundstein 10y agoI think C++'s const is one of the strongest consts I know of. Java/C#'s const on the other hand...
- hota_mazi 10y agoIt's actually too strong and the designers of the language later had to introduce `const_cast` in order to relax it in certain circumstances. In practice, Java's weaker `final` (immutable references) appears to be a reasonable middle ground.
- morbidhawk 10y ago> OO abstractions and patterns OTOH, taught essentially in "elementary school" which possibly makes them seem easier to understand What did I just read, you're joking right?
- patrickmn 10y agoNot joking at all. Functional languages have a reputation for being hard to learn mainly because they aren't what most people learn initially (and switching paradigms is never easy, no matter which direction you're going.) Disclaimer: The above is an opinion. Double-blind trials have not been performed!
- morbidhawk 10y agoI agree that switching paradigms is not easy. The part that sounded like a joke and still sounds like a joke is downplaying the difficulty it is to learn OO abstractions and patterns. Even initially being taught them, does not mean you've really learned nor understood them well. When comparing it to something "elementary" I'd expect something simple like 13+4, not something as complicated as software design.
- patrickmn 10y agoNothing we do is easy for most people... that's why we're highly sought after. What I meant was not that it's easy to do something, rather that it's something that often comes early, and is mandatory, in your journey of discovery. The concepts you learn early on, while not easy to fully grasp, stick, and make other paradigms seem alien.
- Const-me 10y ago> Why compose classes, abstract base classes, etc. when you can compose simple functions For some kind of projects (video games, applied math, anything else that is sufficiently performance or latency sensitive), data structures are just as important as code. And they need to be composed, too. For example, in C++ I can put small structures into couple megabyte-sized vectors, because memory controllers love sequential RAM access. Then I put these vectors in another vector, because address space might be fragmented and memory manager might not be able to give me continuous 1GB buffer, also to save CPU time + RAM bandwidth when growing my dataset to gigabytes. Then I wrap these vectors into another container that creates and maintains an index over the whole dataset using a hash map, because besides sequential access, other times I want to lookup my values by some key, and I want the lookups to run fast. And so on. FP paradigm is just fine for composing functions. AFAIK, FP offers little for composing data structures. And those sophisticated specialized data structures are often the key for writing high-performance code.
- patrickmn 10y agoThere are libraries like https://hackage.haskell.org/package/repa https://hackage.haskell.org/package/repa that make some of these tasks much easier to do. (Write your program/algorithm in terms of these arrays and all operations on them are seamlessly parallelized.) And there's really no reason you can't wrap something by making a new data type that includes the original arrays and an index.. it's just not a class. While it's worth mentioning that Haskell does allow you to get pretty low level, it nonetheless has a GC, and the code you end up writing often looks more like C than FP. Rust is a great alternative that combines a lot of the raw performance and control over memory of C/C++ and good stuff from FP (e.g. sum types/pattern matching.) (Or even better, use something like Haskell and FFI with Rust for performance-critical parts.)
- Const-me 10y agoI never used Rust in commercial projects. But to my knowledge, data structures in Rust are not exceptionally good at composing, because the language lacks raw pointers. In C++ I can add hashmap-based index to existing collection of values without duplicating the values, because I can only keep pointers in the map. I can add linked list-based LRU tracking to existing collection of values. I can use pointers to implement graph-based structures. While there’re workarounds in Rust, such as reference counted pointers, raw pointers in C and C++ are just faster.
- Raknarg 10y agoHonestly I'm not sure if OO is actually easier to understand than FP. I remember when I started programming it was a crappy but simple language called Turing that was procedural and had support for objects and pointers. We weren't really taught classes in my high school course, so everything we did was entirely imperitive. I came across a problem where I had about 20 different entities in a game who all had a special way of updating during each tick, but I didn't want to have to write a switch statement for each one. I looked up "How to have an array of functions", and without knowing it at the time I was trying to implement first-class functions in this language which it just so happened to have. From there it's easy to see how once you understand the concept of first class functions, many FP concepts start to fall in line, and by the way the language was set up it was difficult to use side-effects in this language, generally you use a function to output to the screen or to return a new resulting value. In fact when it finally came around to learning about classes, I had a very difficult time understanding how they worked or what purpose they served, made my Java classes in University difficult for some time. I'm not sure what point I'm making here, I just thought how it was neat looking back that my first language I learned I naturally branched into more FP-oriented programming.
- disantlor 10y agoi'll say on any post here that's even slightly related: learning functional reactive programming (in my case via Bacon.js) improved my code, and my thinking about code, by orders of magnitude. Now, the only bugs are related to me not fully understanding/encoding the business logic and i can make complicated changes with extreme confidence, and as you can see i'm eager to tell people about it.
- crush_xc 10y agoDoes anyone have a solid place to start with functional programming? Don't really care too much about the language it's associated with but would really like to jump into learning the concepts behind it.
- BlahBoy3 10y agoI personally like this one: http://learnyouahaskell.com/chapters http://learnyouahaskell.com/chapters
- aditya42 10y agoAt it's simplest, it's just the use of pure functions[1] and nothing but pure functions. [1]: https://en.wikipedia.org/wiki/Pure_function https://en.wikipedia.org/wiki/Pure_function
- jingwen 10y agoReal World OCaml. https://realworldocaml.org/v1/en/html/prologue.html https://realworldocaml.org/v1/en/html/prologue.html > Real World OCaml is aimed at programmers who have some experience with conventional programming languages, but not specifically with statically typed functional programming. Depending on your background, many of the concepts we cover will be new, including traditional functional-programming techniques like higher-order functions and immutable data types, as well as aspects of OCaml's powerful type and module systems. It's a nice segue into the world of functional programming if you're not ready to give up on imperativeness just yet.
- chriswarbo 10y agoAfter answering this a few times I wrote up a blog post of advice for how to starting programming "more functionally", regardless of language: http://chriswarbo.net/blog/2015-01-18-learning_functional_programming.html http://chriswarbo.net/blog/2015-01-18-learning_functional_pr...
- JCoder58 10y agoScott Wlaschin's site http://fsharpforfunandprofit.com/ http://fsharpforfunandprofit.com/ - For F#, but his articles try to answer the question "why is this useful?" Eric Lippert's Monad Posts, starting at https://ericlippert.com/2013/02/21/monads-part-one/ https://ericlippert.com/2013/02/21/monads-part-one/ - Uses C# to build up Monads using examples.
- munchor 10y agoI thought this was the famous paper by John Huges[1]. [1]: https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.p...
- mpweiher 10y agoSame here. My favorite part of that paper: "However, there is a very important point that is often missed. When writing a modular program to solve a problem, one first divides the problem into subproblems, then solves the subproblems, and finally combines the solutions. The ways in which one can divide up the original problem depend directly on the ways in which one can glue solutions together. Therefore, to increase one’s ability to modularize a problem conceptually, one must provide new kinds of glue in the programming language." We need more kinds of glue. He argues that FP provides one (function composition, a Good Thing™) and lazy FP another (lazy eval, a bit more controversial). But that's not a whole lot, is it?
- marcosdumay 10y agoThe last couple of decades we've seen the rise of exactly two kinds of glue (objects and frameworks) into mainstream use. Two extra may not be a lot, but you aren't getting many more anywhere else. There are also high order types polymorphism, that normally comes with FP but it not inherently linked to it.
- mpweiher 10y agoWell, there's dataflow/pipes-and-filters. Constraints, especially (one-way) dataflow constraints are awesome for gluing stuff together. I've done some work on making messaging more flexible, messaging is pretty powerful glue. But yes, overall, it's been fairly abysmal. Which is why I personally think we need to really, really focus on flexible glue: http://objective.st http://objective.st :-)
- nickpsecurity 10y ago
- msimpson 10y ago> Imperative programming is like building assembly lines, which take some initial global state as raw material, apply various specific transformations, mutations to it as this material is pushed through the line, and at the end comes off the end product, the final global state, that represents the result of the computation. This isn't the best analogy as functional and imperative languages are both often used in a procedural fashion. If I simply replaced "global state" with "immutable arguments", this analogy fits functional programming as well. The fact that the arguments would be copied, however, would be implied. > Each step needs to change, rotate, massage the workpiece precisely one specific way, so that it is prepared for subsequent steps downstream. Every step downstream depend on every previous step, and their order is therefore fixed and rigid. This is more about tight coupling than imperative vs. functional paradigms. In general, imperative methods can be just as loosely coupled as functional methods. It basically comes down to what sort of data you're handling. > Because of these dependencies, an individual computational step has not much use and meaning in itself, but only in the context of all the others, and to understand it, one must understand how the whole line works. This, again, can be true of functional languages as well. You cannot always guarantee that a method is individually useful given the data at hand.
- austincheney 10y agoThere is some faulty assumption that functional programming is never imperative. Functional programming has nothing to do with declarative/imperative programming styles. The "functional" part determines the architecture by which the code is structured opposed to the style (vanity) by which the structure comes together. If you need to compare functional programming against something contrast it against OOP, which is a different architectural approach.
- jackmott 10y ago>Functional programming has nothing to do with declarative/imperative programming styles. nothing!? >The "functional" part determines the architecture by which the code is structured opposed to the style (vanity) by which the structure comes together. No idea what this means.
- jackmott 10y agoDoes article contain references to any enpirical evidence that particular language features or programming idioms have a benefit? Have you noticed that these articles almost never do? they have argument from authority and anectdote. Language research is still in the phase of bad humors and blood letting.
- cholantesh 10y ago>Language research is still in the phase of bad humors and blood letting. Love this. Practically all the claims I've seen are just small code samples accompanied by the author's vague endorsement.
- goalieca 10y agoI've seen an number of papers focusing on the mathematical side of things. While I'm not a PL researcher, it does seem to me that math is the universal language and it seems reasonable to focus on that rather than non-sense concepts like objects.
- jackmott 10y agocan you provide empirical evidence to support your theory?
- cholantesh 10y agoHow would we mathematically represent usability?
- goalieca 10y agoBy capturing relations. If we define an algebra it will have certain properties (eg commutative, associative). You don't think twice when writing a physics equation on how to factor, compose, or compute a value. It comes naturally from the rules of algebra. In category theory we might have different categories. Some might instruct the compiler and programmers that the function obeys certain rules when applying. It could be trivial to parallel or perhaps it specifies a strict sequencing for computation. Following Haskell research, you can really see the evolution as people find more useful generalizations (which in the end, has made things simpler!)
- zinxq 10y agoMy apprehension comes from lack of seeing it in the wild (i.e. scaled businesses). Google primarily uses C++/Java. Facebook: Hack. Twitter tried Scala and as far as I know, abandon it and went to Java. LinkedIn definitely tried Scala, failed, and went to Java. Square is Ruby/Java. I'd like to have something to point to as a success story of a company at scale with functional programming. Anyone know of one?
- andrzejsz 10y agoWhat is wrong with Scala that some companies seem to abandon it in favour of Java?
- hvs 10y agoCompilation in slow. It's also a complex language that can be hard to wrap your head around. That makes it hard to spin up new developers on it.
- problems 10y agoThat's an excellent question - especially given that you can essentially use it as a "functionally enhanced java" as it's not a hard-FP language like Haskell. I'd love to know - maybe it's a question of staffing? More skilled Java programmers around than Scala programmers probably. Also might be easier to work with lower level DB libraries and such, but I don't see why a company that large couldn't develop and maintain their own abstractions.
- jerf 10y ago"especially given that you can essentially use it as a "functionally enhanced java" as it's not a hard-FP language like Haskell" I'm not sure if I can call this "the Haskell community consensus", but a lot of the Haskell community finds Scala too complex to be worthwhile. They find it introduces a lot of complexity above and beyond Haskell, but at the same time, fails to take proper advantage of it and the result is quite dirty, full of special cases, and consequently hard to reason about. So you get a lot of the costs, perhaps even more costs for compliance than a Haskell code base, but you get fewer benefits.
- bischofs 10y agoI have read a lot of articles about learning functional programming to make you a better programmer with conventional OO or imperative languages - but this does not make sense to me. The argument is "learn these concepts that are not available in other languages to make you better at those languages". Can anyone explain?
- stabbles 10y agoI think the most apparent example is that people recognize patterns like `fold` and `map` everywhere once they've seen functional programming. This can be implemented in any language I guess. Most often you'll see explicit & imperative loops being refactored to shorter, descriptive code with anonymous functions, folds, filters and maps
- deleted 10y ago[deleted]
- Jtsummers 10y agoYou can take those concepts and use them in your designs in languages where they're missing, even if you don't use FP or logic languages where they're "native".
- craigsmansion 10y agoBroadly speaking, imperative programming allows one to start coding a solution before one understands the problem. Functional programming is generally more abstract in its approach to modelling the problem. If you get the model wrong, you will not end up with a working solution, forcing you to rethink your model. While imperative programming allows you to reiterate towards a solution as you start to understand the problem better as you work towards it, it's obviously better and faster if your initial model of the problem is more accurate. Functional programming forces you to create a viable model of the problem before you start. If you can extend that discipline over to an imperative language, you will need less iteration and the resulting solution will likely be more elegant. The argument is not (or shouldn't be) about concepts, but about paradigms and discipline.
- ht85 10y ago
- hota_mazi 10y agoI wish someone would one day write a more objective article, such as "Why some aspects of functional programming are useful while some other aspects are an inconvenience to produce good code".
- prmichaelsen 10y agoUnfortunately such articles don't get the same number of clicks
- developer2 10y agoBecause there are no valid objective qualities as to why functional programming is any "better" or "worse" than the alternatives. At the end of the day, you're instructing the machine to do the same work, regardless as to the structure of the code you're writing. Functional vs. an alternative is nothing more than visually different styles that result in developers having a personal preference. Some languages offer optimizations for certain constructs, but even those depend on the implementation found in each language. A functional language doesn't automatically grant objectively better qualities, whereas a specific functional language might provide advantages that have everything to do with that specific language rather than the fact it happens to be functional. Functional languages are interesting and the right tool for the job for many people. But they are not better, and when you have developers fighting hard to defend their language as "better", recognize that has a lot more to do with their ego than anything based on facts.
- deleted 10y ago[deleted]
- BuuQu9hu 10y agoThis misguided blogger thinks that object-based programming is necessarily about members and inheritance. It isn't. It's about message-passing and uniform interfaces and bundles of state and behavior. It's about ravioli code and modules and separation of concerns.
- stabbles 10y agoObject-based programming is not about inheritance by definition.
- kazinator 9y agoThere are "Blub" languages which are such that if you don't use inheritance to connect two record types T1 and T2, either to a common supertype S, or to each other, then T1 and T2 are not substitutable. The users of these languages came up with the term "object based" for that situation in order to try to linguistically connect that to object-oriented programming somehow. In real OOP, we don't have to use inheritance for objects of different types to be substitutable, so "object based" doesn't exist as a separate phenomenon. We use inheritance when two or more things are internally similar, such that they can share a chunk of implementation. If things are similar only externally (API level) but have totally different internals, then we don't use inheritance. OOP is happening when we substitute objects of different types into the same code and they work, regardless of whether those objects are related to each other by inheritance. "Object based" is when we cannot do that. It's basically a new (or not so new any more) term for "abstract data type" which is used when the abstract data type language supports obj.function(arg) syntactic sugar. If we take Wirth's Modula-2 or Pascal exactly as-is (two languages exemplifying abstract data typing support) and then add the "obj.function(arg)" sugar, they suddenly become "object based".
- draw_down 10y agoWell, if you're a fan of functional programming then the "bundles of state and behavior" are... bad.
- BuuQu9hu 10y ago
- jorgeleo 10y agofunctional is simple, oop is easy https://www.infoq.com/presentations/Simple-Made-Easy?variant=show&utm_expid=14598459-9.T3WK-0v0SHy21kchz98AYg.1&utm_referrer=https%3A%2F%2Fwww.google.com%2F https://www.infoq.com/presentations/Simple-Made-Easy?variant...
- panic 10y ago> If a company hires software engineers, there’s a good chance that critical parts of their business exist in the form of computer code. Therefore the growth of that business is closely linked to the maintainability of that code. Businesses adapt and grow constantly, they perpetually change. New features and new offerings to customers are added every day. Existing features are revisited, strategies are revised, whole business models are pivoted. There are advantages to functional programs, but I wouldn't say they're any easier to change than imperative programs. In fact, it's often more work to change a program where all functions depend purely on their arguments. Instead of adding a single imperative state update, you have to add a new argument to a whole group of functions and thread state through them appropriately. Patterns like monads and monad transformers can make this easier, but massive stacks of monad transformers have their own issues (http://blog.ezyang.com/2013/09/if-youre-using-lift-youre-doing-it-wrong-probably/ http://blog.ezyang.com/2013/09/if-youre-using-lift-youre-doi...). (And besides, most functional programming languages apart from Haskell support mutable state (e.g. ML ref cells, Scheme set!) -- pure functions aren't fundamental to the functional paradigm.)
- efnx 10y agoRefactoring Haskell code has been the best refactoring experience I've ever had, and I've worked with "a lot" of imperative languages. IMO the biggest boost in maintainability is by adding a (typed) compilation step - after that the stronger the type system, the better.
- iLemming 10y agoFunctional programming is here already and even in OOP languages. What really matters though - is why we should be using languages like Clojure, Haskell, and Ocaml.
- aglavine 10y agoThe irony is that Haskell had sorting wrongly implemented for awhile