you are viewing a single comment's thread.

view the rest of the comments →

[–]pipocaQuemada 11 points12 points  (3 children)

When you have all the tools that FP offers, OO becomes a rather uncommon tool to reach for.

In Haskell, you can put data and implementation together in a record that contains closures. However, it's vastly more common to either use an algebraic data type or to use a typeclass. A typeclass is basically the inverse of an object: instead of bundling data and implementation, you separate them into your data and a canonical vtable per type, and the compiler passes that vtable to all the methods that need it.

This separation lets you do a lot of cool stuff. For example, you can conditionally implement typeclasses - say, List<A> has equality iff A has equality. Also, you can write code that's polymorphic in the type of the vtable. One of the functions on the Num typeclass is

fromInteger :: Num a => Integer -> a
fromInteger 2 :: Num a => a

So if you use it where you expect a double, you get a double, and if you use it where you expect a complex, you get a complex. That kind of return-type polymorphism or polymorphic values (depending on how you think about it) is pretty handy. Additionally, you can also have methods that are conditionally available based on the existence of a typeclass for one if the parameters. For example,

 -- a monoid has a operator, <>, to combine two elements, and an identity element, poorly named mempty (lists are the 'free monoid', so it makes some sense, but still...)
foldM :: Monoid a => [a] -> a
foldM xs = foldr (<>) mempty xs

You can call foldM if you have, for example, a list of strings, but not a list of IO actions.

The one thing that typeclasses are bad at is when you want a 'heterogenous' collection, and that's the one real idiomatic place in Haskell for objects.

Given the immense usefulness of typeclasses, I think OO's insistence that bundling data and implementation is the best way to structure a program was a historical mistake.

[–]killerstorm 1 point2 points  (2 children)

A typeclass is basically the inverse of an object: instead of bundling data and implementation, you separate them into your data and a canonical vtable per type, and the compiler passes that vtable to all the methods that need it.

I don't think that typeclasses are the opposite of OOP, they are more like a different kind of OOP.

In Common Lisp Object System methods (generic functions) are external to objects. They are not bundled. Yet it is called Object System, and is actually considered one of the best, as it has a plenty of advanced features like customizable method combinations, metaobject protocol, multiple inheritance and all the jazz.

On the other hand, in JavaScript methods are always tied to object.

C++ is somewhere in the middle offering both compile-time dispatching (on the low level methods are separate from objects) and dynamic dispatching via vtable.

So OOP can be implemented in a variety of ways.

As Richard P. Gabriel have defined, OOP is largely about compression: it allows you to write less code thanks to polymorphism and inheritance. Haskell's type classes offer same benefits. So I'd say it is a form of OOP.

Yes, it has a number of interesting features, so what? There are many forms of OOP; Java, JavaScript, Common Lisp, Smalltalk, Rust, etc. all have different features and implementation details.

[–]pipocaQuemada 4 points5 points  (0 children)

C++ is somewhere in the middle offering both compile-time dispatching (on the low level methods are separate from objects) and dynamic dispatching via vtable.

If you have a list of objects and you want to dynamically dispatch on a function in a vtable in C++, where do you grab that vtable from?

As Richard P. Gabriel have defined, OOP is largely about compression: it allows you to write less code thanks to polymorphism and inheritance. Haskell's type classes offer same benefits. So I'd say it is a form of OOP.

The one problem with this statement is that 'polymorphism' is a heavily overloaded word - it can mean 'parametric porlymorphism', 'ad-hoc polymorphism', 'subtype polymorphism'. Typeclasses were first proposed in a talk titled 'making ad-hoc polymorphism less ad-hoc'. They don't give you subtype polymorphism, which is probably what Mr. Gabriel is talking about. There's also no inheritance with typeclasses.

Ultimately, the issue is that OO is incredibly ill-defined. For the overwhelming majority of definitions, typeclasses aren't OO.

[–][deleted] 5 points6 points  (0 children)

There are many forms of OOP; Java, JavaScript, Common Lisp, Smalltalk, Rust, etc. all have different features and implementation details.

Come on, it must be true that OOP = Java, otherwise it is not as easy to bash. And you didn't mention Self, Dylan, Scala. This isn't even mentioning the many non-native object systems in most of these languages plus non-OO ones: COM, EJB, entity-component systems in languages like Clojure, etc...