

Where FP meets OO - stefanobaghino
http://christopherhunt-software.blogspot.com/2014/12/where-fp-meets-oo.html

======
amelius
I'm not sure that OO-ness is a desired property.

Alexander Stepanov, original creator of the STL:

"I find OOP technically unsound. It attempts to decompose the world in terms
of interfaces that vary on a single type. To deal with the real problems you
need multisorted algebras - families of interfaces that span multiple types. I
find OOP philosophically unsound. It claims that everything is an object. Even
if it is true it is not very interesting - saying that everything is an object
is saying nothing at all. I find OOP methodologically wrong. It starts with
classes. It is as if mathematicians would start with axioms. You do not start
with axioms - you start with proofs. Only when you have found a bunch of
related proofs, can you come up with axioms. You end with axioms. The same
thing is true in programming: you have to start with interesting algorithms.
Only when you understand them well, can you come up with an interface that
will let them work."

More discussion:

[http://www.quora.com/Was-object-oriented-programming-a-
failu...](http://www.quora.com/Was-object-oriented-programming-a-failure)

~~~
al2o3cr
"You do not start with axioms - you start with proofs. Only when you have
found a bunch of related proofs, can you come up with axioms. You end with
axioms."

Um, what? You have no FACTS to _do_ proofs with without axioms; they are the
fundamental statements one assumes to be true to define a logical system.

Somebody who insists that they need "multisorted algebras" while
misunderstanding a fundamental definition in mathematical logic is
exceptionally confused...

~~~
v64
I interpreted this to be a top down vs bottom up argument.

In mathematics, we certainly have ZFC as an axiom system now, but mathematics
was performed for thousands of years without a "stable" axiomatic base. For
example, calculus was developed before the axiomatic delta-epsilon definition
for limits was created. The math was developed first, and it was only after
the fact that mathematicians went back and set the theory on a stable
theoretical footing.

Therefore, I believe Stepanov suggests a bottom up approach: You write an
algorithm that performs your work first, and then once you have that, you can
refactor the code into classes that encapsulate the various parts of your
existing algorithm.

------
otas
Alan Kay was inspired by the real world, mostly biology back when psychotropic
substances were rather popular. That's were the problems start. The real world
systems are: 1) unpredictable - except for those who can forecast the future.
2) Unreliable 3) Slow 4) Uncoordinated - except if you believe someone runs
the world. 5) Unmaintainable - just ask someone on human maintenance (drug
research etc). 6) Naturally autonomous

Point 6 is very critical, because in von-neumann architectures you will end up
having a shared memory and trying to give an autonomous memory to each agent,
will end up very suboptimal, and no zipper, COW of any other FP trick can
change that.

You just cannot afford to write your software like the real world, and you
don't even have intelligent agents of human ability as building blocks...

~~~
seanmcdirmid
For point 6, that wasn't Kay but the simula crowd who invented OOP before Kay.

FP is like math: it isn't based on biology or natural human thought, but
rather the truth of math. OOP is much more fuzzy, you can say things that you
can't nescessarily prove are true via biased naming and relating (just like
you could say and think as a person). Math is great and useful, but there is a
reason we haven't evolved into straight up Vulcans yet.

~~~
otas
Well seems that simula OOP was a bit more like java/c++. It was Kay who had
the message passing idea, and the smalltalk people still don't consider
java/c++/simula-derivatives as true OOP languages because they miss that.

[http://c2.com/cgi/wiki?AlanKaysDefinitionOfObjectOriented](http://c2.com/cgi/wiki?AlanKaysDefinitionOfObjectOriented)
[http://userpage.fu-
berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay...](http://userpage.fu-
berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en)

~~~
seanmcdirmid
I think you have it backwards: OOP in Simula was more bizarre since all
objects basically ran as co-routines. It isn't until Smalltalk where we get
the non-autonomous objects that we are familiar with today.

------
Pxtl
Am I the only one who finds the goalposts gave moved for FP? it used to be
lambdas/lexical closures that were the big must-have FP feature, then it was
immutability. Now that we're seeing traditionally-OO languages sport a raft of
immutable types and good support for lexical closures, now it's all about
higher-kinded-types.

For a while, the big feature was homoiconicity and tail-call-optimization
until lisp fell out of favour with language geeks.

Does FP just mean "has features of my favorite self-proclaimed-functional-
language"?

~~~
Denommus
Functional Programming is just composing a program with pure functions,
nothing else.

Immutability and closures are required for that, because mutability may break
homoiconicity (which is required for purity), and lack of closures means you
can't pass state around.

Higher-kinded types are very useful for helping with lots of functional
abstractions, but they are a type system feature and have nothing to do with
FP. If someone claims that, this person doesn't understand FP or type systems.

OCaml and Standard ML are two examples of languages without higher kinded
types but are just as good as Haskell for FP.

(Although they have a powerful module system to compensate for that).

~~~
the_af
> because mutability may break homoiconicity (which is required for purity)

Are you sure you meant that? My (admittedly weak) understanding of
homoiconicity is that it's unrelated to either purity or (im)mutability. Isn't
homoiconicity related to the program text and its AST? Aren't there languages
such as Haskell which encourage pure functions but are not homoiconic?

I'm pretty sure you meant something else...

~~~
abathologist
I bet "referentiality" was meant. It would make sense as a replacement for
"homoiconicity".

~~~
abathologist
I bet "referential transparency" was meant. It would make sense as a
replacement for "referentiality". oops :(

------
mariusmg
"Scala is the only language that I know of that marries the world of FP and
OO"

You can do that in C#/F# too. There's nothing special about Scala from this
point of view.

~~~
mercurial
OCaml was doing that before any of them.

~~~
ufo
Although I find it interesting how Ocamlers only rarely reach for the OOP bits
of the language. I think that this is in part due to the powerful module
system that language has.

~~~
mercurial
Indeed. Also, the object system doesn't have the reputation of being very
fast. That said, it lets you use structural typing, which is extremely handy
once in a while.

------
tel
While I'm reasonably open-minded about using some parts of OO at higher levels
of organization (or at least just genuine modules), I'm not sure Akka is the
right place to land there. Functions which are just typed as `a -> ()` have
lost (or hidden) all their interesting structure.

~~~
virtualwhys
Certainly Haskell, for example, is one of the few languages richly endowed
with a non-existent module system, but I personally don't know of a
distributed computing environment that does preserve types across machine
boundaries in any language. I must be missing something, please enlighten.

If type preservation in distributed computing was a trivial engineering
problem it would have already been solved and widely used. As it stands Akka
is enjoying fairly widespread enterprise adoption in the distributed computing
market, untyped-ness notwithstanding.

Interestingly, as saryant points out, Akka 3.0 apparently will be typed,
although I was under the impression that the typed actor project was
experimental/a long way off/not a sure thing. Guess things have changed for
the better...

~~~
tel
I'm not claiming it's a solved problem; I'm claiming that the current
solutions are lacking.

You can take it as standing on the outside and throwing stones, but it's not
malicious. I _want_ something better.

~~~
virtualwhys
Yeah, I know, same deal with type safe database query DSLs, none have hit the
mark yet, including M$'s Linq to Sql, Scala's Slick, Haskell's Esqueleto and
Opaleye, etc.

Seems we're on the brink of a completely type safe distributed stack, but
argghingly not quite there. Maybe in another couple of years the computing
community will have turned the corner.

FWIW, from the outside looking in Haskell seems to be kicking ass in terms of
language evolution (7.8 and 7.10 in particular). Here on the Scala side of the
fence we've got a ways to go, probably 4 years or so until the dust settles
with various compiler forks and research work brings a (hopefully) vastly
improved Scala into being.

~~~
tel
Yeah! I want to see an EDSL impl of a nicely typed Tutorial D sometime
already!

Personally, I don't know that I care about the distributed part of the stack.
I want something like Erlang's actor model in Haskell even on one machine. I
think if there was a nicely typed way to do that (and see pipes-concurrent and
mvc for nice examples) there'd be some fantastic "large scale" application
operating space that would get opened up.

Akka does this somewhat below par with Erlang. I'd wonder if a GHC
implementation of straightforward single machine Erlang's semantics could do
better with typed effects and true asynchronous exceptions. This would be nice
even with just effect typing (e.g. untyped channels and lots of living in some
IO-alike) and could be a good interpreter target for simpler strongly-typed
organizational designs.

I started fiddling with this (under the name hotep) a few months ago and got
sidetracked but it keeps coming up!

------
josephlord
_Scala is the only language that I know of that marries the world of FP and OO
and thus does not need to “throw the baby out with the bathwater”._

Have you had chance to try Swift yet. It could do with Tail Call Optimisation
but I do think it can already be used for functional programming.

~~~
k__
I think LiveScript does a good job too.

But it's a bit of a niche product, not a LISP and more like Python.

------
Denommus
OCaml also has both, and its object system is probably more powerful.

~~~
ClosureSpin
How come?

~~~
Denommus
Besides the object system, OCaml has a powerful module system, with first-
class modules and functors (which is already basically very equivalent to what
you'd expect from objects).

Besides that, objects have structural typing, and you can even create objects
without classes (somewhat similarish to anonymous classes, except instead of
interfaces you have the structural typing to give you something like
statically typed duck typing).

OCaml also has multiple inheritance and friend classes.

------
hawleyal
Ruby is pretty FP/OO friendly.

------
mlawlerau
Interesting article Chris.

------
dschiptsov
In CLOS.

~~~
dschiptsov
Why there are so many ignorant idiots in the world?

According to Alan Kay, the essence of OO approach (or paradigm if you wish) is
a synthesis of a few fundamental concepts (like a Lisp itself) where _not a
single one can be removed_ because harmony (or balance) would be destroyed,
and an ugly, mediocre construction would emerge instead (Java).

The concepts are:

* First-class closures - isolated, share-nothing abstractions.

* Nesting of closures, so they could have an internal structure.

* Message passing as _the only way of communication_ among closures.

As long as you follow these three principles, you have "generics" for free,
because all the operations are mere messages.

These are three of four principles upon which Smalltalk has been built upon.

Here is an illustration, assuming that we are implementing message passing as
simple as a procedures call.

    
    
       (define (kons x y)
          (lambda (m)
            (cond ((eq? m 'car) x)
                  ((eq? m 'cdr) y)
                  (else (error "bottom!")))))
    
       (define (kar x)
          (x 'car))
    
       (define (kdr x)
          (x 'cdr))
    

Notice that using only these abstractions we could implement a unified list
structure of Lisps (recall Escher's hands).

This is (surprise!) the "core" of Erlang - extending of closure-based language
with immutable data with explicit message-passing, to create first-class
_agents_ (servers, etc).

Where is inheritance? Inheritance is just a _protocol_ which specifies what to
do with unknown message instead of signaling an error or returning a bottom
like in Haskell.

What is MOP could be found in Wikipedia. Smalltalk was its ancestor.

What is CLOS? It is a DSL embedded in a Lisp (based on structures made out of
closures) which implements some or other subset of MOP. MIT Scheme, for
example, has SOS.

So FP meet OP in CLOS.

~~~
gclaramunt
> Where is inheritance? Inheritance is just a protocol which specifies what to
> do with unknown message instead of signaling an error or returning a bottom
> like in Haskell.

Care to explain? Doesn't make any sense to me...

~~~
dschiptsov
A protocol is like a set of rules. It it specifies, for example, that each
object (a closure) has special bindings, which holds references to its class
(which is also a closure) and to itself, so it could send a massage to its
super or to self. Classes could have its own methods (inner closures).

Basically, when you send a message, you have to specify a symbol, that
corresponds to a method name, and parameters. The protocol specifies the
"routing", like if there is no method that corresponds to this name, then send
(forward) the very same message to your superior (exactly like they do in
army, which is an implementation of the actor model).

If supers doesn't know what to do with the message, then there is panic - an
exception.

The protocol also specifies the rules of shadowing of symbols, such that a
method could be redefined (shadowed) within a closure, so it "overrides" a
method with the same name from its ancestors.

Object methods (inner closures) could send messages to classes (invoking class
methods) and then doing something with a returned value. Usually, there is
some syntactic sugar for that.

In short, inheritance is a set of rules, and these rules could be implemented
using various mechanism, like explicit message-passing (a-la Erlang) or
implicitly, using procedures calls.

Brian Harvey in classic Berkeley CS61A explained these ideas much better than
me.

[https://www.youtube.com/watch?v=7u3pp7JCAIU](https://www.youtube.com/watch?v=7u3pp7JCAIU)

~~~
gclaramunt
yes, that part makes sense, but in Haskell, an unknown "message" is a compiler
error, and bottom represents abnormal termination (e.g exception or even non
termination), I don't really understand how that's related to inheritance.

~~~
dschiptsov
I am not sure that an unknown message could be caught at compile time, because
we don't know everything in advance. I also don't think that static type
checking is the only way to program.

In that toy example I should return an error, because '() is a legit value.

------
thesz
[https://parleys.com/play/51c1994ae4b0d38b54f4621b/chapter33/...](https://parleys.com/play/51c1994ae4b0d38b54f4621b/chapter33/about)

After about 53-th minute Odersky gets lost in side effects in a very simple
code.

This is why there's nothing elegant about Scala.

~~~
wernerb
The OP points out that immutable code is the standard in Scala. You have
picked an example where Odersky gets 'lost' in mutable code. If anything, this
video (and your comment) makes the case for immutable and side-effect free
code using Actors and FP, as apparently it can be confusing.

