4 ms·
This is something I spend a lot of time thinking about myself - it seems like functional program ought to be > object-oriented program which ought to be > proce
by commandlinefan 6y ago
This is something I spend a lot of time thinking about myself - it seems like functional program ought to be > object-oriented program which ought to be > procedural programming. However, I've almost never seen a functionally-designed application "in the wild" and honestly, it's pretty rare to even see an object-oriented one. It seems like every program I ever dig into is mostly written procedurally, even if it's written in a language that supports higher-level abstractions. And, for the most part, software works. As much as I love the concept of pure functional programming, how do we really know that "functional programming is better" and that's not just wishful thinking on our part? Looking forward to digging into this - hopefully the author can make a better case than others have.
- leephillips 6y agoNeither paradigm solves the expression problem. This forces people to break the paradigm as the code grows. Look at the code in some Julia packages, and you will see good use of abstractions around a language design where the expression problem does not exist. This is practical stuff, being used in applied scientific research on a large scale.
- trumpeta 6y agoHere's how you can solve expression problem using object algebras: https://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf https://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf
- Twisol 6y agoI'll make a stronger statement than "can": I have and do productively use object algebras in my day-to-day in Java. It's a really fantastic tool when you need an "interface" that governs multiple types or across more than one receiver. Even when you're not trying to solve the expression problem. When you're defining an interface on a type that doesn't need to appear in its own method parameters or return types, and where the actual type doesn't matter (as in classic OOP), Java interfaces are fine. But not all problems are best framed this way.
- trumpeta 6y agoPersonally I prefer being on the other end of the expression problem - where extending underlying data (mainly sum types) is the costly operation. Like in Rust, because it actually makes you think about the data model instead of the implementation. Adding new functions is "free" in the sense that it's not going to break your model. But I'm curious if you don't find object algebras in Java cumbersome and kind of fighting the type system? Because while I like this kind of thing in Scala, in Java it feels very much against the design of the language.
- Twisol 6y ago> Personally I prefer being on the other end of the expression problem I agree, I prefer sum types in general. And you can still get dynamic dispatch from trait objects (in Rust), so you have both approaches at your disposal. (In Java, all you have is a hammer...) > But I'm curious if you don't find object algebras in Java cumbersome and kind of fighting the type system? Yes and no. I try to use them where they make more sense than OO-style interfaces, so somewhat by definition I don't find them any more cumbersome than OO-style interfaces would be. Java feels like it has a dearth of modeling techniques, so even a seemingly-niche one like object algebras gives me a lot more to work with. Serializers/deserializers are a good fit for an object-algebra approach, since you don't want to define those methods directly on the data type you're serializing (if you even have control over that type). Traditionally algebraic types, where you can combine two instances to get a third, are also a good fit. (From a Haskell perspective, you can think of the `x.add(a, b)` as explicitly naming the dictionary of typeclass methods you'd get from writing `a + b` -- kind of like `a +_x b`, if you will.) And there's almost no choice if you want to define a signature over multiple types -- you need a mediator object anyway. It's pretty ergonomic if you stay nearby these and similar patterns.
- trumpeta 6y agoThank you, this was very illuminating!
- marcosdumay 6y agoFrom the wikipedia: > The expression problem is a new name for an old problem. The goal is to define a datatype by cases, where one can add new cases to the datatype and new functions over the datatype, without recompiling existing code, and while retaining static type safety (e.g., no casts). Why should I care about recompiling? That's an implementation detail. Taking the compilation stuff out, it looks very similar to classy lenses.
- lastofus 6y ago> Why should I care about recompiling? That's an implementation detail. Sometimes you don't have access to 3rd party src code you call into, hence why you can't always modify and recompile it.
- adamnemecek 6y agoIts more about the modification rather than recompilation.
- marcosdumay 6y agoBut type classes solve the modification problem. (Even tough no language that I know of solves the recompilation.)
- scns 6y agoDoes that mean Kotlin's Extension Functions solve it?
- leephillips 6y agoI don’t know. Don’t ask me, ask Wikipedia.
- wtetzner 6y agoI think it's more about not being able to recompile third-party library code than your own code.
- lalos 6y agoTry out Parsec library in Haskell (http://book.realworldhaskell.org/read/using-parsec.html http://book.realworldhaskell.org/read/using-parsec.html). If you are familiar with parsing in general you'll see benefits immediately. Also FP tends to promote composition over inheritance (see: https://en.wikipedia.org/wiki/Composition_over_inheritance https://en.wikipedia.org/wiki/Composition_over_inheritance).
- rovolo 6y agoYou aren't going to see entirely functional applications "in the wild" because it's convenient to keep the top layer procedural. But, it's generally useful to use OO and functional design for components. Then you combine the components in a procedural manner. Here's a decent example of creating functional components and gluing them together imperatively: https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell https://www.destroyallsoftware.com/screencasts/catalog/funct... OO and Functional are just good design goals for making an easy to use API for your components. Even if those components are written in C, I think you'll find that many components are designed to be: Object Oriented: - has an interface - hides implementation details Functional: - the same input always gives the same output. I.e. there's no hidden state changes which you need to keep track of You can think of it like concrete vs cement. The OO and functional components are the rocks and rebar in concrete, and imperative code is the cement. The rocks make the concrete stronger, but it's easier to shape with cement in between the rocks and rebar.
- da39a3ee 6y ago> it's pretty rare to even see an object-oriented one That's not even vaguely true. OO is the dominant paradigm in many areas of commercial programming, including web backends, phone client code, desktop applications using GUI frameworks, written in Python, Java, C#, Objective C, Ruby, etc. Think about Java -- that basically mandates OO.
- commandlinefan 6y ago> Think about Java -- that basically mandates OO. You would think, but in my experience most people write mostly procedural code in Java: data-only types that expose all their properties with getters and setters, and all methods (and most data) declared static. Most Java developers write as if they were working in COBOL.
- da39a3ee 6y agoInteresting; I admit I've been involved in very little java development. You must be exaggerating a tiny bit though? We all know that the kingdom of nouns gets a lot of stick, but surely it's not fair to characterise the community of java programmers as being numerically dominated by those who do not understand how to create distinct instances of their nouns?
- pkphilip 6y agoWhy is the comment being modded down? What he/she said is true.
- leafboi 6y agoYou're completely right. There is no theory behind program design and structure. We have no way of measuring why one paradigm is better than another paradigm. This is the first thing that needs to be solved before we can unequivocally prove that one paradigm is better than the other. The first question that needs to be answered is, what exactly is a well designed programming language? What exactly is a well structured program? Until you are able to answer the questions above axiomatically we are doomed to run in circles forever.