What is the relationship between use of typeclasse...
# arrow
j
What is the relationship between use of typeclasses (or the Kotlin equivalent of interfaces with extension functions) and functional programming? Neither are required for core FP goals such as immutability, purity, and referential transparency. So, why does this pattern repeatedly show up in FP?
s
You're right, for those, you don't need type classes. But if you want to model error results and keep your functions pure, if you want to be able to model side effects in a pure and referential way, want to model asynchronous tasks, dependency injection, type classes can be a powerful tool.
s
Typeclasses allow for ad-hoc polymorphism. Or in different words, it allows you to define functionality for a type without inheritance. I.e
data class class Foo(val name: String, val age: Int)
generates
hashCode
,
equals
and
toString
from its properties. But in Haskell, you do that separately since there is no inheritance.
*data* Person = Person String Int
here we define a
record
Person
with
String
&
Int
properties. By changing it to
data Person = Person String Int deriving(Eq, Show, Hash)
we now tell the compiler to automatically add an instance for the
Eq, Show & Hash
typeclass. Which is the equivalent of
toString
,
hashCode
&
equals
. This behavior goes much further, but as you can see it allows you to implement behavior outside of a class instead of using inheritance. Similar to how
Comporator
and
Comparable
work in Java. ad-hoc vs inheritance based polymorphism. This goes much further than just
Eq
,
Show
&
Hash
of course.
j
@simon.vergauwen So polymorphism achieved through typeclasses is more flexible than inheritance. But couldn't one remain in OOP and choose to exclusively use typeclasses?
@streetsofboston Could you explain a little about the types of problems that would come up if one didn't use typeclasses to model the things you mention?
s
Yes, exactly. Yes, one can definitely stay in
OOP
land and still get benefits from typeclasses! Or exclusively use them.
j
@simon.vergauwen thanks!
I've been thinking about this question some more. I've formed a possible explanation. Please tell me if it's a compelling one. The primary reason why use of typeclasses (and co.) is more prevalent in FP than OO is that typeclasses are difficult-to-impossible to use when state is encapsulated i.e. when access is restricted in order to protect mutable state. Such encapsulation of mutable state dominates OO design. So, as a result, does inheritance in order to access that state. On the other hand, since FP requires state be immutable, state encapsulation is irrelevant, and there's no limit to the extent to which typeclasses can be applied. So this pattern dominates. To clarify, by "encapsulation", I'm thinking more specifically of "information hiding".
s
Right, you could put it that way. “Such encapsulation of mutable state dominates OO design”, this absolutely correct! And could explain why OOP or Java/Kotlin developers are not actively looking for typeclasses. However as an OOP developer in the passed, I was often looking for something like typeclasses to overcome inheritance in cases where I don’t own the types. However I’ve never felt that I was exposes more than I want to when using FP. I have access to the same access modifiers, and tools available as before.
👍🏾 1
j
@simon.vergauwen Is it possible to use the
private
access modifier on a data class field and still use typeclasses to operate on the field?
s
Yes, but only if you expose them from their
companion object
.
Copy code
class Person(private val name: String, private val age: Int) {
  companion object {
    fun eq(): Eq<Person> = 
      Eq { a, b -> a.name == b.name && a.age == a.age }
  }
}
j
Ah, sneaky! 😄 Thanks!
m
In principle, in the functional paradigm, you are actively trying to avoid any kind of encapsulated mutable state. Typeclasses for me are like patterns in OO (like a Observer, Delegate, Factory, etc.); they just model a way to solve a problem
The primary reason why use of typeclasses (and co.) is more prevalent in FP than OO is that typeclasses are difficult-to-impossible to use when state is encapsulated i.e. when access is restricted in order to protect mutable state.
👍🏾 1