Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The point of the class instance (the "singleton") is not performance, it's that it exists independently of any instance of the type, so it can be used for factories and such.

This however, is not my main concern, and as you remarked, it does not fit very well in OO, which is why it isn't in my proposal.

On to the interesting part.

You want multiple adapters, rather than multiple interfaces, precisely because you want retroactive interface implementation. That's really the crux here. So either you pass two adapters, or you make a class combining the two adapters. I think both solution create too much bloat to be acceptable.

For me, equality isn't so rare. Both identity (==) and structural equality (equals(), done right) pop up with some regularity. Each time you use a map, for instance. And functional languages are perfectly capable of structural equality.

While Scala typeclases are implemented with implicit objects, typeclasses precisely avoid using implicit conversions. You still have the original object, the typeclasses just provides functions to work with it. It's only an implicit conversion in the same sense that passing an ArrayList to a function expecting a List is implicit conversion. This is manifest in Scala where you require a typeclass using some sort of type bound.



Thanks for the explanations. Yes, there seems to be an impedence mismatch when trying to import the concept of Haskell type classes to OOP languages.

WRT a combined adapter class, it'd look like this in Kotlin:

  class FooBarAdapter(val x: Baz, private val y = Foo(x), private val z = Bar(x)) : Foo by y, Bar by z
A bit bloaty, but still a single line of code.

(I know you already know this, I'm writing it here for Kotlin newbies).


The problem there is composability. Foo and Bar might come from different libraries. Also it's very common to define one typeclass in terms of another, often several layers deep. It's easy enough to define a wrapper at an outer layer, but when you have an EitherT[WriterT[Future, MyLog, ?], MyError, MyValue] it becomes quite clunky to apply wrappers to MyLog and Future.


Wow, actually this hadn't made it to my bag of trick yet.

It's very nice, though I can see that becoming quite heavyweight when you nest these calls (either heavy from the overhead, or from the syntax - at least you get to decide).




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

Search: