Hacker News new | past | comments | ask | show | jobs | submit login

I think there's a huge opportunity for FP+OO... but that OO will have to be rethought from first principles (which are lacking in OO).

More specifically, I think OO-style code interactions are great but that they need to be separated from ambient mutability, subtyping, subclassing, inheritance, etc. Late binding/open corecursion is really cool however.

I would like to see a language which starts with ML modules as a base and build a totally novel semi-OO system into FP. I don't think it would, at the end of the day, look much at all like OO the way that OO appears today, but I think it could still gather many of the advantages while maintaining ease of reasoning, good type inference, etc.




I think there's a huge opportunity for FP+OO... but that OO will have to be rethought from first principles (which are lacking in OO). More specifically, I think OO-style code interactions are great but that they need to be separated from ambient mutability, subtyping, subclassing, inheritance, etc.

This has already happened. Ideally, good object-oriented code should always prefer immutability over mutability, should prefer interface polymorphism over inheritance polymorphism, should prefer has-a relationships (the OO version of composition) over is-a relationships (subclassing), and so on. Much of this was originally figured out a very long time ago.

So the issue isn't that these standards don't exist; it's that they aren't widely understood among users of object-oriented languages. That, in turn, is because OO is so widely used by so many programmers, including a lot of people with very limited formal training in computer science, that most users of OO languages have very little exposure to any of the literature about what constitutes well-crafted object-oriented code. Certainly less so than in FP, which benefits (in this department) from the fact that it hadn't even begun to escape the ivory tower in any sort of serious way until just a few short years ago. In short, object-oriented programming is a victim of its own success.

It doesn't help that the first really widespread object-oriented language wasn't particularly object-oriented, either.


> Ideally, good object-oriented code should always prefer

Really what I'm referring to is a language which outlaws instead of one that leaves it up to preference. And by outlaw I don't mean entirely, but instead a language which requires the programmer explicitly opt into these richer domains as they are needed.

My understanding is that while these principles are understood as valuable, OO is generally constructed as too permissive to enforce them.

In a similar story, unbounded recursion is generally "bad" in almost every part of a program---nobody likes mysteriously hanging programs---but only total languages have a formalism which allows you to profitably outlaw it.

So I'm convinced there are the beginnings of the theory of objects lurking around out there even if they rarely see the light of day (really) in practice. But I also recognize that modern functional semantics grew over the last 80 years. I don't think (maybe I'm wrong) that the whole package of OO has had so long to mature.


> So the issue isn't that these standards don't exist; it's that they aren't widely understood among users of object-oriented languages.

But we're talking about language design. I think enforcing constraints is much (maybe all, from a certain point of view and definition of "constraint") of what a programming language ought to do. Haskell code is principled because the language is principled, not because of conventions passed from an ivory tower.

Also do you know of any languages built around those principles you mention? It sounds like studying such a language might make OO click for me a little more.


I feel that Golang in many ways is on that path, the way it does not allow no-subclassing really got me thinking.

> I don't think it would, at the end of the day, look much at all like OO the way that OO appears today

Won't it be more like a Actor-oriented thing then?


"I feel that Golang in many ways is on that path, the way it does not allow no-subclassing really got me thinking."

I'm pretty decent in Haskell and fluent in Go at this point, and it really depends on what you mean by that. Is Go a certain brand of very refined OO? Yes. I've even found certain ideas from PF are surprisingly adaptable [1], the "surprise" being that it's not the usual "Look, Ma, I can map/filter/reduce!" that an OO language borrows from the FP world, which Go is actually really hostile to. (Go does have closures and they are important, but the type system precludes a lot of the "good stuff".)

However, is Go headed in the direction of Haskell? No. It's definitely not. Trying to turn it into Haskell would be nothing but pain. Mutability is pretty fundamental in Go, and while there's a culture of isolating it to goroutines, the language itself does little to help with that.

[1]: http://www.jerf.org/iri/post/2923


> it really depends on what you mean by that. Is Go a certain brand of very refined OO? Yes.

Indeed that's what I meant.


I'm not certain. I think the interesting aspects would be in considering what's missing from open corecursion. I don't think the actor model is much better foundationally---it's a destination, not a beginning or a path.


Uhm...you mean like Moby?

http://moby.cs.uchicago.edu/


Perhaps, I'll take a look at it.


What is "open corecursion"?


Corecursion is when you define the meaning of a type by a coalgebra like

    x -> F x
for some pattern functor F. So, for instance, defining an infinite stream like

    newtype Stream = Stream { runStream :: (X, Stream) }
is corecursion. The interesting part is that whatever defines the stream is forced to fix the Stream type immediately. Open (co)recursion in OO langauges occurs when the recursive type is left undefined (i.e., self is passed in). This allows you to change the type of the object at every step if desired.

The similar game in a recursive function might be defining face like so

    fact :: (Int -> Int) -> (Int -> Int)
    fact recur n = n * recur (n-1)
We "tie the knot" by passing fact to itself

    fix f = f (fix f)

    fix fact :: Int -> Int
which would allow us to add extra cases as needed

    let term recur n = if n == 0 then 1 else recur n

    > fix fact 3
    -- infinite loop
    > fix (term . fact) 3
    6
So this is a kind of "mixing" of recursive functions. Open corecursion lets you do OO-like "mixing" of corecursive functions.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: