Java interface and class like Haskell: differences and similarities?

While I am studying Haskell, I noticed its type class, which should be a great invention that came from Haskell.

However, on the Wikipedia page in the classroom class :

The programmer defines a type class by defining a set of functions or constant names, together with their corresponding types, which must exist for each type that belongs to the class.

What seems closer to the Java interface for me (quoting the Wikipedia (Java) interface page ):

An interface in the Java programming language is an abstract type that is used to indicate the interface (in the general sense of the word) that classes should implement.

These two options look pretty similar: the class type restricts the type behavior, and the interface limits the class behavior.

I wonder what are the differences and similarities between a class of classes in Haskell and an interface in Java, or maybe they are fundamentally different?

EDIT: I noticed even haskell.org admits that they are similar . If they are so similar (or are they?), Then why is the type of class handling such advertising?

MORE EDIT: Wow, so many great answers! I think I will have to let the community decide which one is better. However, while reading the answers, they all seem to simply say that "there are many things that a class can do, because the interface cannot or must handle generics." I can't help but wonder if there is anything that can work with interfaces, if not. . In addition, I noticed that Wikipedia claims that typeclass was originally invented in a 1989 article * "How to make ad-hoc polymorphism less ad hoc," while Haskell is still in its cradle, while Java- The project was launched in 1991 and first released in 1995. Thus, maybe, instead of having typeclass similar to interfaces, on the contrary, typeclass influenced these interfaces? Are there any documents or documents to support or refute this? Thanks for all the answers, they are all very instructive!

Thanks for all the inputs!

+89
java interface haskell typeclass
Aug 4 2018-11-21T00:
source share
10 answers

I would say that the interface is similar to a class of type SomeInterface t , where all values ​​are of type t -> whatever (where whatever does not contain t ). This is due to the fact that with the type of inheritance relations in Java and similar languages, the called method depends on the type of object they are invoking and nothing else.

This means that it is very difficult to do things like add :: t -> t -> t , with an interface where it is polymorphic for more than one parameter, because there is no way for the interface to indicate what argument type and return type The method is the same type as the type of the object on which it is called (ie, the type "itself"). Using Generics, there are several ways to fake this by creating an interface with a common parameter that is expected to be of the same type as the object itself, for example, as Comparable<T> does, where you should use Foo implements Comparable<Foo> so that compareTo(T otherobject) type is of type t -> t -> Ordering . But this still requires the programmer to follow this rule, and also causes a headache, when people want to create a function that uses this interface, they must have recursive typical type parameters.

Also, you will not have things like empty :: t , because you are not calling the function here, therefore it is not a method.

+38
Aug 04 2018-11-21T00:
source share

What looks like class interfaces and classes is what they call and describe a set of related operations. The operations themselves are described through their names, inputs and outputs. Similarly, there may be many implementations of these operations, which are likely to differ in their implementation.

With that aside, here are some notable differences:

  • Interface methods are always associated with an instance of an object. In other words, there is always an implied parameter 'this', which is the object on which the method is called. All inputs to a type class function are explicit.
  • An implementation of an interface should be defined as part of a class that implements the interface. Conversely, an instance of the instance class can be defined completely separately from the type associated with it ... even in another module.
  • The type class allows you to define a default implementation for any of the specific operations. Interfaces are strictly type specifications, without implementation.

In general, I think it's fair to say that class classes are more powerful and flexible than interfaces. How do you define an interface to convert a string to any value or instance of an implementation type? This, of course, is not impossible, but the result would not be intuitive or elegant. Have you ever wanted to be able to implement an interface for a type in some compiled library? This is easy to do with type classes.

+36
Aug 04 2018-11-21T00:
source share

Type classes were created as a structured way of expressing “special polymorphism,” which is basically a technical term for overloaded functions. A type class definition looks something like this:

 class Foobar a where foo :: a -> a -> Bool bar :: String -> a 

This means that when you apply the foo function to some type arguments that belong to the Foobar class, it looks for an implementation foo specific to this type and uses it. This is very similar to the situation with operator overloading in languages ​​such as C ++ / C #, with the exception of more flexible and generalized ones.

Interfaces serve a similar purpose in OO languages, but the basic concept is somewhat different; OO languages ​​come with a built-in concept of type hierarchy, which Haskell simply does not have, which complicates the situation somewhat, because interfaces can include both overloading using subtypes (that is, by calling methods in the corresponding instances, and subtypes that implement the interfaces that make their supertypes) and through flat type-based dispatch (since two classes implementing the interface may not have a common superclass that also implements it). Given the enormous additional complexity introduced by subtypes, I suggest it is more useful to think of type classes as an improved version of overloaded functions in a language without OO.

It is also worth noting that type classes have much more flexible dispatching methods — interfaces usually apply to only one class that implements it, while type classes are defined for a type that can appear anywhere in the signature of class functions. An equivalent of this in OO interfaces would allow the interface to determine how to pass an object of this class to other classes, define static methods and constructors that would choose an implementation based on what type of return is required in the context of the call, define methods that take arguments of the same type, as a class that implements the interface, and various other things that are not broadcast at all.

In short: they serve similar purposes, but the way they work is slightly different, and type classes are much more expressive, and in some cases easier to use because of working with fixed types, and not from parts of the inheritance hierarchy.

+21
Aug 04 2018-11-21T00:
source share

I read the answers above. I feel that I can answer a little more clearly:

A class like Haskell and a Java / C # interface or Scala symbol are basically the same. There is no conceptual difference between them, but there are differences in implementation:

  • Haskell class types are implemented with "instances" that are separate from the data type definition. In C # / Java / Scala, interfaces / features must be implemented in a class definition.
  • Haskell type classes allow you to return this type or native type. Scala traits do as well (this.type). Note that "self types" in Scala are a completely unrelated function. Java / C # requires a messy generic workaround to approximate this behavior.
  • Haskell's class types allow you to define functions (including constants) without entering a parameter of type "this". Java / C # interfaces and Scala features require the input parameter "this" for all functions.
  • Haskell class types allow you to define default implementations for functions. Thus, the features of Scala and Java 8+ interfaces. C # can approximate something like this using extension methods.
+11
Sep 05 '14 at 0:12
source share

Watch Phillip Wadler talk Languages ​​of Beliefs, Evolution, and Programming . Wadler worked on Haskell and was a major contributor to Java Generics.

+9
Aug 14 2018-11-11T00:
source share

Read the “Software Extension and Type Class Integration” section for examples of how type classes can solve a number of problems that interfaces cannot.

Examples listed in the document:

  • the problem of expression
  • structure integration problem,
  • Independent extensibility issue
  • the tyranny of dominant decomposition, scattering and tangling.
+8
Aug 14 2018-11-21T00:
source share

Programming Minds has an interview about Haskell with Phil Wadler, the inventor of type classes, which explains the similarities between interfaces in Java and type classes in Haskell:

Java method such as:

  public static <T extends Comparable<T>> T min (T x, T y) { if (x.compare(y) < 0) return x; else return y; } 

very similar to the Haskell method:

  min :: Ord a => a -> a -> a min xy = if x < y then x else y 

So, type classes are associated with interfaces, but the real correspondence will be a static method parameterized with the type, as indicated above.

+8
Jan 20 '14 at 15:58
source share

I cannot speak with a level of "deception" if it seems like a good thing. But yes classes are similar in many ways. The only difference I can think of is that in Haskell you can provide behavior for some class operations like:

 class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y) x == y = not (x /= y) 

which shows that there are two operations equal (==) and not equal (/=) , for things that are instances of a class of type Eq . But an unequal operation is defined in terms of equal (so you only need to provide it) and vice versa.

So, in possibly-non-legal-Java, which would be something like:

 interface Equal<T> { bool isEqual(T other) { return !isNotEqual(other); } bool isNotEqual(T other) { return !isEqual(other); } } 

and the way it will work is that you will need to provide one of these methods to implement the interface. Therefore, I would say that the ability to partially execute the behavior you want at the interface level is a difference.

+5
Aug 04 2018-11-21T00:
source share

They are similar (read: have a similar use) and are probably implemented similarly: polymorphic functions in Haskell take a 'vtable' under the hood, listing the functions associated with the typeclass class.

This table can often be displayed at compile time. This is probably less true in Java.

But this is a table of functions, not methods. Methods are tied to an object; the cool Haskell classes are not.

Look at them like Java generics.

+4
Aug. 04 2018-11-21T00:
source share

According to Daniel, interface implementations are defined separately from data declarations. And, as others have pointed out, there is a simple way to define operations that use the same free type in several places. Therefore, it is easy to define Num as a class. Thus, in Haskell, we get the syntactic benefits of operator overloading, without having any magical overloaded operators - just standard types.

Another difference is that you can use methods based on a type, even if you don't already have a specific value for that type!

For example, read :: Read a => String -> a . Therefore, if you have enough information about the other types that hang around how you will use the “read” result, you can let the compiler figure out which dictionary to use for you.

You can also do things like instance (Read a) => Read [a] where... , which allows you to define a reading instance for any list of readable things. I do not think this is possible in Java.

And all this is just standard one-parameter classes, without any workarounds. As soon as we introduce multiparameter types, a whole new world of possibilities appears, especially with functional dependencies and type families that allow you to insert much more information and calculations into the type system.

+3
Aug 04 2018-11-21T00:
source share



All Articles