30

What are the similarities and the differences between Haskell's TypeClasses and Go's Interfaces? What are the relative merits / demerits of the two approaches?

Jeremy Jose
  • 355
  • 3
  • 4
  • APIs that take in a one-method `interface` could be re-written as taking a function type. See https://stackoverflow.com/a/63557675/12817546. –  Aug 24 '20 at 23:37

5 Answers5

25

Looks like only in superficial ways are Go interfaces like single parameter type classes (constructor classes) in Haskell.

  • Methods are associated with an interface type
  • Objects (particular types) may have implementations of that interface

It is unclear to me whether Go in any way supports bounded polymorphism via interfaces, which is the primary purpose of type classes. That is, in Haskell, the interface methods may be used at different types,

class I a where
    put :: a -> IO ()
    get :: IO a

instance I Int where
    ...

instance I Double where
    ....

So my question is whether Go supports type polymorphism. If not, they're not really like type classes at all. And they're not really comparable.

Haskell's type classes allow powerful reuse of code via "generics" -- higher kinded polymorphism -- a good reference for cross-language support for such forms of generic program is this paper.

Ad hoc, or bounded polymorphism, via type classes, is well described here. This is the primary purpose of type classes in Haskell, and one not addressed via Go interfaces, meaning they're not really very similar at all. Interfaces are strictly less powerful - a kind of zeroth-order type class.

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
  • 4
    Indeed, the only relation between the two seems to be that in both cases the "methods" live independent of the "classes". That's about it. – Jörg W Mittag Jun 05 '10 at 21:20
  • 2
    Go's interfaces support "bounded polymorphism," as strictly defined by that Wikipedia article, by virtue of simply naming the interface you desire in a function's signature. E.g., if I write "func foo(a, b IBar)", then the compiler ensures I can only pass in structs supporting IBar. However, Haskell's typeclasses supports non-struct types, and even compound bindings (e.g., func foo(a, b (IBar && IBaz)) is illegal in Go, but (IBar a, IBaz a) => foo :: a -> b -> ... is perfectly legal). You'd have to make a compound interface in Go to do something similar (vis. io.ReadCloser). – Samuel A. Falvo II Feb 15 '15 at 00:18
9

I will add to Don Stewart's excellent answer that one of the surprising consquences of Haskell's type classes is that you can use logic programming at compile time to generate arbitrarily many instances of a class. (Haskell's type-class system includes what is effectively a cut-free subset of Prolog, very similar to Datalog.) This system is exploited to great effect in the QuickCheck library. Or for a very simple example, you can see how to define a version of Boolean complement (not) that works on predicates of arbitrary arity. I suspect this ability was an unintended consequence of the type-class system, but it has proven incredibly powerful.

Go has nothing like it.

Community
  • 1
  • 1
Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
7
  1. In haskell typeclass instantiation is explicit (i.e. you have to say instance Foo Bar for Bar to be an instance of Foo), while in go implementing an interface is implicit (i.e. when you define a class that defines the right methods, it automatically implements the according interface without having to say something like implement InterfaceName).
  2. An interface can only describe methods where the instance of the interface is the receiver. In a typeclass the instantiating type can appear at any argument position or the return type of a function (i.e. you can say, if Foo is an instance of type Bar there must be a function named baz, which takes an Int and returns a Foo - you can't say that with interfaces).
sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • 4
    The lack of polymorphism heavily restricts the degree to which Go intefaces are related to type classes. I would say that without polymorphism in the instance methods, they're not really related, other than superficially. – Don Stewart Jun 05 '10 at 21:11
  • That people are asking about it shows that they clearly are related. I would say that Go interfaces are a strict subset of what Haskell's typeclasses offer. E.g., everything you can do in Go is possible in Haskell (trivially, even), but the reverse isn't true. – Samuel A. Falvo II Feb 15 '15 at 00:21
  • I'm not sure how you want to make the type "Bar" a requirement. Normally you have an "instance of the type class" which requires the type instance to be of a specific type. But the type class itself only contains placeholders ("future" typeclass instances) which are not bound to a specific type. Go's interfaces are different in that they bind implicitly to types whereas Haskells type classes have to be instantiated / explicitly implemented. – Sebi2020 Sep 26 '20 at 13:17
5

Very superficial similarities, Go's interfaces are more like structural sub-typing in OCaml.

snk_kid
  • 3,457
  • 3
  • 23
  • 18
3

C++ Concepts (that didn't make it into C++0x) are like Haskell type classes. There were also "axioms" which aren't present in Haskell at all. They let you formalize things like the monad laws.

Zifre
  • 26,504
  • 11
  • 85
  • 105
solrize
  • 31
  • 1