Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between C# interface and Haskell Type Class

I know that there is a similar question here, but I would like to see an example, which clearly shows, what you can not do with interface and can with Type Class

For comparison I'll give you an example code:

class Eq a where 
    (==) :: a -> a -> Bool
instance Eq Integer where 
    x == y  =  x `integerEq` y

C# code:

interface Eq<T> { bool Equal(T elem); }
public class Integer : Eq<int> 
{
     public bool Equal(int elem) 
     {
         return _elem == elem;
     }
}

Correct my example, if not correctly understood

like image 534
giokoguashvili Avatar asked Jul 21 '17 08:07

giokoguashvili


People also ask

What is difference between C plus and plus C?

There is a major difference between C and C++. The C language is a procedural one that provides no support for objects and classes. On the other hand, the C++ language is a combination of object-oriented and procedural programming languages.

What is difference between A and A in C++?

'a' is a character literal. It's of type char , with the value 97 on most systems (the ASCII/Latin-1/Unicode encoding for the letter a ). "a" is a string literal. It's of type const char[2] , and refers to an array of 2 char s with values 'a' and '\0' .

What is are 3 differences between C and C++?

C does no support polymorphism, encapsulation, and inheritance which means that C does not support object oriented programming. C++ supports polymorphism, encapsulation, and inheritance because it is an object oriented programming language. C is a subset of C++. C++ is a superset of C.

How is C++ better than C?

Compared to C, C++ has significantly more libraries and functions to use. If you're working with complex software, C++ is a better fit because you have more libraries to rely on. Thinking practically, having knowledge of C++ is often a requirement for a variety of programming roles.


2 Answers

Typeclasses are resolved based on a type, while interface dispatch happens against an explicit receiver object. Type class arguments are implicitly provided to a function while objects in C# are provided explicitly. As an example, you could write the following Haskell function which uses the Read class:

readLine :: Read a => IO a
readLine = fmap read getLine

which you can then use as:

readLine :: IO Int
readLine :: IO Bool

and have the appropriate read instance provided by the compiler.

You could try to emulate the Read class in C# with an interface e.g.

public interface Read<T>
{
    T Read(string s);
}

but then the implementation of ReadLine would need a parameter for the Read<T> 'instance' you want:

public static T ReadLine<T>(Read<T> r)
{
    return r.Read(Console.ReadLine());
}

The Eq typeclass requires both arguments have the same type, whereas your Eq interface does not since the first argument is implicitly the type of the receiver. You could for example have:

public class String : Eq<int>
{
    public bool Equal(int e) { return false; }
}

which you cannot represent using Eq. Interfaces hide the type of the receiver and hence the type of one of the arguments, which can cause problems. Imagine you have a typeclass and interface for an immutable heap datastructure:

class Heap h where
  merge :: Ord a => h a -> h a -> h a

public interface Heap<T>
{
    Heap<T> Merge(Heap<T> other);
}

Merging two binary heaps can be done in O(n) while merging two binomial heaps is possible in O(n log n) and for fibonacci heaps it's O(1). Implementors of the Heap interface do not know the real type of the other heap so is forced to either use a sub-optimal algorithm or use dynamic type checks to discover it. In contrast, types implementing the Heap typeclass do know the representation.

like image 67
Lee Avatar answered Sep 22 '22 04:09

Lee


A C# interface defines a set of methods that must be implemented. A Haskell type class defines a set of methods that must be implemented (and possibly a set of default implementations for some of the methods). So there's a lot of similarities there.

(I guess an important difference is that in C#, an interface is a type, whereas Haskell regards types and type classes as strictly separate things.)

The key difference is that in C#, when you define a type (i.e., write a class), you define exactly what interfaces it implements, and this is frozen for all time. In Haskell, you can add new interfaces to an existing type at any time.

For example, if I write a new SerializeToXml interface in C#, I cannot then make double or String implement that interface. But in Haskell, I can define my new SerializeToXml type class, and then make all the standard, built-in types implement that interface (Bool, Double, Int...)

The other thing is how polymorphism works in Haskell. In an OO language, you dispatch on the type of the method the object is being invoked on. In Haskell, the type that the method is implemented for can appear anywhere in the type signature. Most particularly, read dispatches on the return type you want — something you usually can't do at all in OO languages, not even with function overloading.

Also, in C# it's kind of hard to say "these two arguments must have the same type". Then again, OO is predicated on the Liskov substitution principal; two classes that both descend from Customer should be interchangeable, so why would you want to constrain two Customer objects to both be the same type of customer?

Come to think of it, OO languages do method lookup at run-time, whereas Haskell does method lookup at compile-time. This isn't immediately obvious, but Haskell polymorphism actually works more like C++ templates than usual OO polymorphism. (But that's not especially to do with type classes, it's just how Haskell does polymorphism as such.)

like image 40
MathematicalOrchid Avatar answered Sep 22 '22 04:09

MathematicalOrchid