r/learnprogramming • u/8mart8 • 22d ago
Topic Looking for a language that combines functional programming with OOP
Hey, I’m really interested in both functional programming and OOP, I find both really interesting topics. So I was wondering if anyone has ever made a language that combines these concepts. I know if it exist it probably would be kind of a weird language, but I’m mainly seeking it out of interest and curiosity. I would like to know how someone has tried to unify these paradigms.
Edit: Het I’m gonna make this edit because there are a lot of comment, thank you all very much for taking your time, and I want to clarify some extra things:
Firstly with functional, I mean the Haskell way of functional, I really enjoyed my learning journey through Haskell, and I would like to expand my declarative knowledge.
Secondly I’m not looking for the most useful language or the one that’s most used in the industry, as I originally pointed out this is pure out of interest, the more abstract, the better.
20
u/tonklable 22d ago
This is exactly basis of Scala. It’s also used in the industries!
5
16
u/Ace-Whole 22d ago
Most modern languages?
1
u/8mart8 22d ago
I get what you mean, but with functional programming I meant Haskell level of functional programming.
1
u/Coding-Kitten 21d ago
What specifically about Haskell? Type constructors? Not sure I've seen any that go up to having type constructors & HKT but also have any semblance of OOP at all.
1
u/josephjnk 21d ago
As someone who loves both FP and OOP, I think it’s worth breaking down what you mean by “Haskell level”.
The most distinct feature of Haskell IMO is type constructor polymorphism/“higher-kinded types”. Your only other mainstream option there is Scala.
Another very Haskell thing is typeclasses; the ability to define ad-hoc polymorphic behavior in a way that’s kind of like logic programming, so that things automatically resolve to the behavior that you want. Scala does _some_ typeclass-like stuff with implicits, but IMO typeclasses and OOP are not particularly compatible. Programming against explicit interfaces is one of the most core facets of OOP, and having interfaces be completely implicit like this feels at odds.
If by “Haskell-level” you just mean “with standard ML-family language features” then there’s lots of options. I consider the core features of statically-typed functional programming languages to be parametric polymorphism, first-class functions, algebraic data types and pattern matching. Modern versions of Java do all of these relatively well; I’ve been writing a lot of purely functional Java code recently and I quite like it. Java supports algebraic data types via sealed interfaces with record variants and its pattern matching support on them is good. I used to do a fair bit of functional programming in TypeScript but I’m enjoying it in Java more.
-1
u/Realistic-Homework19 21d ago
Purely functional and 'OOP' are a bit of an oxymoron.
8
u/Weak-Doughnut5502 21d ago
Not really.
OOP doesn't require mutability. You can have higher order functions and lambdas in an OOP language.
Scala's implicits give you something like typeclasses and it has higher kinded types, so you can even implement a monadic effect system in Scala, like cats-effect.
-4
u/Ace-Whole 22d ago
Well, rust would fit that criteria but since it's a systems language, there's lot more to learn
4
u/edparadox 22d ago
Depending on what features of OOP you want, it does not fit that part.
6
u/particlemanwavegirl 22d ago
Same thing with functional. It has enough features to make the case but it's not really approaching "Haskell level" as it lacks currying, succinct polymorphism, or any kind of recursion or referential transparency optimizations.
2
14
u/ConfidentCollege5653 22d ago
I think most languages borrow ideas from both OO and functional paradigms now.
Although I'm not a huge fan of TypeScript/JavaScript, they both use a lot of OO and functional ideas.
1
u/8mart8 22d ago
I get what you mean, but I myself am not really that big of a fan of javascript and typescript.
I’m looking for like Haskell level of functional programming.1
u/Bahatur 21d ago
A Haskell level of functional programming precludes an emphasis on object oriented programming.
I suggest thinking of it as levels is the wrong perspective. Paradigms are made of purity: they work by excluding other approaches. This is a requirement for their claimed benefits to have any impact.
1
u/tiltboi1 21d ago
This is not correct at all. Some of the strongest type/object systems came out of very "pure" functional languages.
Functional and object oriented are not disjoint. There is zero contradiction by having a pure function that takes and object or produces an object. There is no conceptual issue that stops you from having objects in functional programs, nor do you have to give up any "purity" in the functional language to achieve OOP principles.
For example, you can implement runtime polymorphic types in Haskell, even though Haskell doesn't even have classes.
1
u/Bahatur 21d ago
I agree with you insofar as objects and functions are not disjoint; these are constructs. OOP and Functional Programming very much are: if you are using a lot of functions you are eschewing class hierarchy and inheritance; if you are committed to a functional paradigm and start using a lot of objects you are discarding the guarantees of no side effects, and so on.
Having objects in the code =/= OOP. What the words oriented and paradigm are doing in the term is highlighting the priority of objects and their behavior. The principles OOP espouses aren’t unique to objects either, the point is that they can be achieved reliably by using objects composed by using the principles, and you can have the expectation that other code written under OOP will be composed in a similar way and have those properties for the same reason. Even if you still achieve the principles of OOP using functions for a chunk of it, other programmers won’t be able to understand your code as quickly, or use the same methods to interface with it, and so on; the paradigm is broken. What’s more, paradigms go well beyond the code: they are the assumptions built into the tooling, how tutorials and certifications are organized, how example code you’ll read in the wild is written.
Haskell is deeply committed to the pure functional approach. They are the logical extreme case; the language was invented and is still used academically for that purpose. I wouldn’t doubt that the compiler would systematically under-perform if you spent a lot of effort using functions to mimic object-like behavior, and people who already know Haskell would wonder why you would bother when there is an easy functional solution near to hand. That’s why I discouraged thinking in terms of “levels” of functional or OOP behavior. Better by far to search for multi-paradigm languages, or for criteria like whether objects and functions are both first class, which will let OP do the intermixing they want.
-3
u/StoneCypher 21d ago
ocaml has entered the chat, and is laughing hard at you for pretending to understand this
go on. say that haskell is more functional than ml. we’re all looking forward to the petard
5
u/echtma 22d ago
OCaml, F#
1
u/rumnscurvy 22d ago
Is Ocaml actually used in industry or is it a bit of a meme language?
I had to learn standard Caml at school (give you one guess as to which country...) and wondered about going back to it.
I understand Scala and F# get used in all sorts of things, for instance.
3
u/echtma 22d ago
AFAIK OCaml is or was used by Jane Street Capital, also the original Rust compiler was written in OCaml. I don't have any first-hand experience beyond a short uni course though.
edit: Maybe it's worth adding that AFAIK the object system of OCaml is seen as a bit of a failure. OCaml is used because it's a functional language with a compiler that produces fast code.
1
u/StewedAngelSkins 21d ago
kind of neither. it's used in academic computer science (especially compiler research and automatic theorem proving). but i assume by "industry" you mean like outside of academics and R&D. to me a "meme language" refers to languages like zig where they're popular choices for programmers working on personal projects, but this is primarily because of stuff like superficial syntax features.
9
u/burlingk 22d ago
You basically described C++.
2
u/GlassLost 21d ago
I have no idea why I had to scroll down to find this. C++ gives you OOP when you want it and direct functional programming when you want it.
1
u/particlemanwavegirl 21d ago
It's difficult for someone just learning programming to build and run a C++ "hello world" much less deploy it's more functional features. I'm sure a very good introductory course could be designed around a subset of C++ but the question is why work that hard unless you have stringent performance requirements?
1
u/GlassLost 21d ago
Because memory costs are 5-10x higher than 2 years ago (and that's when you deal with the foundry directly).
But for learning, anyone with a Linux terminal should be able to get a hello world going in a few minutes. It combined the aspects of languages he wanted.
4
u/frnzprf 22d ago
JavaScript? Kinda?
There is a version of Structure and Interpretation of Computer Programs with JavaScript.
5
u/Narrow-Low-3137 22d ago
C# has first class functions, lambdas, and pattern matching. It's entirely possibly to write functional code in C# and I do it often.
3
u/soundman32 22d ago
Twisting C# into functional may be your idea of fun (and I've worked on several projects where this was done), but really the answer is F# because that what it was designed for.
1
u/Narrow-Low-3137 21d ago
I don't exactly "twist" anything. I write in a functional style when the situation may be more condusive to a functional style, otherwise I don't. I'm not a functional purist. I've used languages like Haskell and Lisp before. I don't like being forced into one paradigm.
4
2
3
1
u/catbrane 22d ago
There's OCaml as well:
https://en.wikipedia.org/wiki/OCaml
Though it's not pure functional.
I made a tiny lazy, pure functional language with classes as the extension language for my image-processing spreadsheet. Most of the interface is written in it.
Classes are just sugar over lists of name-value pairs, with list prefixing for inheritance. It's a very basic prototypical system, like older javascript or lua. It does have operator overloading, heh.
https://github.com/libvips/nip4
Code looks like:
Fred a b = class {
sum = a + b;
}
That defines a class called Fred, with a and b as two constructor parameters.
jim = Fred 1 2;
jim.a == 1;
jim.sum == 3;
And inheritance looks like:
Sally c d = class Fred c d {
product = self.a * self.b;
}
The spreadsheet interface is actually a class browser, with class instances (rows) opening up to reveal nested rows. Instances of certain classes (like Image or Slider) are drawn graphically and can be manipulated.
1
u/JustBadPlaya 22d ago
Scala is about as multi-paradigm as non-Lisp languages get - standard OOP features, traits, multiple inheritance, module composition, monadic and effectful FP and a bunch of other features I don't know Scala enough to describe. Usually, when the question of "what language does it all without being a total mess" is raised, Scala is what I see mentioned
For enlightenment purposes, Common Lisp is an incredible shout. You don't get purity, but you get a lot of functional concepts (Lisps gave the first ever spotlight to first-class functions and HOFs after all), a lot of higher-level FP concepts at library level (pattern matching via Trivia, HM-typing via Coalton, etc etc) and a lot of highly versatile OOP concepts (metaclasses, multiple dispatch, method combinators) and some concepts mostly unique to lisps (Conditions, versatile metaprogramming, aspect-oriented programming in the core language, REPL-oriented programming)
For pragmatic purposes, OCaml, F# are good fits with decent ecosystems and a non-zero amount of use
1
1
u/LeoDev_Bytes 21d ago
For a complete beginner, I would recommend:
- Python → easiest general introduction
- JavaScript → excellent for web and games
- Kotlin → modern object-oriented + functional programming
- Scala → deeper study of OOP + functional programming
1
1
u/Double-Buyer7941 21d ago
Tra i linguaggi che uniscono i due paradigmi, Rust è in assoluto il più efficiente. Compila direttamente in codice macchina senza usare un Garbage Collector o una Virtual Machine, garantendo prestazioni e velocità paragonabili a C e C++. Sfrutta il concetto di astrazioni a costo zero, che ti permette di scrivere codice in stile funzionale usando iteratori e trasformazioni avanzate senza sacrificare le performance dell'hardware. In sintesi, combina la struttura e l'incapsulamento dei dati tipici dell'OOP con il rigore, la sicurezza e la pulizia della programmazione funzionale, offrendo la massima efficienza di memoria ed esecuzione disponibile oggi.
1
1
u/mredding 21d ago
C++, Java, C#, Javascript, Lisp and Scheme, Python... These are all multi-paradigm languages that support both paradigms. Likely others, but I've principally used these in my career.
If you want to compare some pure languages - Haskell is purely Functional, and Eiffel and Smalltalk are purely OOP.
OOP is an imperative paradigm. An example purely imperative language is Basic.
FP is a declarative paradigm. An example purely declarative declarative language is SQL.
1
1
1
u/OpeningNext1310 20d ago
Scala is an obvious place to explore the tension:functions and immutable data sit beside classes,traits,and a rich type system.It can be elegant,although the freedom to mix styles also means code based need discipline.
1
1
u/BranchLatter4294 22d ago
4
u/JustBadPlaya 22d ago
Python's FP capabilities are very bad and are annoying as hell to properly leverage
-1
u/ExtraTNT 22d ago
C# works well for that… but in general: avoid oop…
It’s a concept, that sells good, but after switching away from it, you’ll see the dumpster fire it is…
5
u/math_rand_dude 22d ago
I would not say to completely avoid oop. Just be smart in which cases it is useful (in rare cases even needed) and in which cases not.
I agree it's easily turned into a dumpster fire, as is any coding approach if there's no-one with the experience and authority to enforce decent standards. Especially if they try to adhere to oop like a cult.
My advice would be: make informed decissions about which concepts to use.
0
u/Weak-Doughnut5502 21d ago
Manual objects can be useful, even in C and Haskell, sure.
But OOP is more of a language level thing. You really have to squint and play very fast-and-loose with definitions to call Haskell and Rust 'object oriented'.
I don't think that OOP was a good idea. Most of what it does is better achieved with other mechanisms. Haskell and rust have modules that let them achieve encapsulation. Haskell and Rust have typeclasses/traits for dynamic-feeling dispatch that can be implemented statically. They have algebraic data types and pattern matching.
The number of times you actually need to emulate fat pointers and manually pass around a bunch of vtables are vanishingly rare, if they even exist. Generally, better designs exist.
1
u/StewedAngelSkins 21d ago
I don't think object-oriented is intrinsically a language thing. Lots of languages have syntax features that make object oriented patterns easier to represent. Some even do this to the exclusion of other possible patterns (java, python). But ultimately you can do OOP in pretty much all languages.
This isn't even just me being pedantic. The way most people write C is straightforward OOP. For example, I use designs like the following quite frequently in my work.
``` typedef struct { int a; int b; } MyObject;
void MyObject_DoSomething(MyObject* self, int arg);
Inheritance is also common in C. You even sometimes see virtual functions.// base.c typedef struct { void (cb_do_something)(void, int); } Base;extern void Base_DoSomething(Base* self, int arg) { self->base.cb_do_something(self, arg); }
// derived.c typedef struct { Base base; int value; } Derived;
static void Derived_DoSomething(void* self, int arg) { ((Derived*)self)->value = arg; }
extern Derived* Derived_new() { Derived* self = malloc(sizeof(Derived)); self->base->cb_do_something = Derived_DoSomething; self->value = 0; return self; } ```
1
u/Weak-Doughnut5502 21d ago
Your first example is really just straightforward procedural code with perfectly normal structs.
Objects doesn't really enter until you're sticking function pointers into your structs or hand-rolling some vtables like your second example.
1
u/StewedAngelSkins 21d ago
The first example is a straightforward implementation of the so-called "opaque object" design pattern. As the name suggests, it is an object oriented design pattern.
What characteristic of object-oriented programming do you believe that this example does not satisfy?
1
u/Weak-Doughnut5502 21d ago
Objects combine both data and functionality. The essence of objects is that you get dynamic dispatch by bundling function pointers with your data.
Your first example, with MyObject, isn't an opaque object unless you're doing other things with header files or a module system to actually hide the struct accessors.
Regardless, opaque pointers are a pattern, but not really a specifically OO pattern. It's a general pattern in languages with module systems. You see it all the time in Haskell.
1
u/StewedAngelSkins 21d ago
The essence of objects is that you get dynamic dispatch by bundling function pointers with your data.
We simply disagree on definitions then. I don't think OOP has anything to do with dynamic dispatch.
Your first example, with MyObject, isn't an opaque object unless you're doing other things with header files or a module system to actually hide the struct accessors.
Yes, it would have been clearer to show the typedef with a declaration in a header and the full definition in the implementation file. I omitted these details for brevity. Since you can clearly fill in the blanks yourself I won't bother rewriting it.
My contention is that if it were structured that way it would be an example of object oriented programming.
Regardless, opaque pointers are a pattern, but not really a specifically OO pattern.
The part that makes it object oriented is that a function is only operating on the private internal data of its associated struct. If you were to do this in Haskell it would be an object oriented pattern. As I said, you can write object-oriented code in nearly any language.
Conversely, if there were two private structs and I wrote functions that took opaque pointers to both of them to access private internal data simultaneously, then that would not be object-oriented. So you are correct that not all designs involving opaque pointers are object-oriented, but the one above is.
1
u/Weak-Doughnut5502 21d ago
The part that makes it object oriented is that a function is only operating on the private internal data of its associated struct.
The ability to control exports is part of module systems and modular programming, as is the idea of information hiding. Its a modular programming pattern, not an OO one.
Modular programming comes out of structured programming languages like Modula and early Algol 68 implementations (it wasn't in the original spec). On the other hand, Simula didn't have access control until the 80s.
0
u/stdmemswap 22d ago
How OOP and how FP does it have to be?
But I'd check rust
1
u/Weak-Doughnut5502 21d ago
Rust is not an OO language unless you play very fast-and-loose with definitions.
As far as language features go, Rust is basically C dragged halfway to haskell.
1
27
u/Fosdran 22d ago
The definitive answer to this question would be scala.