21

In object-oriented languages (e.g; Java and Python) we can make objects/instances from classes. In Haskell we can make instances from type-classes, ex:

data ShirtSize = S | M | L      -- Here ShirtSize is a enum data-type

class MyEq a where
  (==) :: a -> a -> Bool
instance MyEq ShirtSize where   -- Here ShirtSize is an instance of the MyEq type-class
  S == S = True
  M == M = True
  L == L = True
  _ == _ = False

My question is: What does instance mean in haskell? In java we can make instances from classes, but in haskell it seems like instances are types (like ShirtSize) which you can apply type-class functions on (e.g the (==) function from MyEq). Am I right? and also what is an instance in Haskell compared to an instance/object in Java?

August Jelemson
  • 962
  • 1
  • 10
  • 29
  • 20
    It's more like "`implements Interface`" in Java. – Bergi Jul 03 '17 at 13:25
  • 3
    I think you nailed it with "instances are types (like ShirtSize) which you can apply type-class functions on (e.g the (==) function from MyEq).". Hardly any room left for an answer after that. Is there further confusion we can comment on when we respond? – Daniel Wagner Jul 03 '17 at 13:30
  • 1
    Read the section Typeclasses 102 from http://learnyouahaskell.com/making-our-own-types-and-typeclasses gives a really good description i think – Viktor Mellgren Jul 03 '17 at 13:31
  • 3
    I think "instance" doesn't mean "it can be instantiated", but rather "this type is an instance of this type class, so its methods can be used". – Bergi Jul 03 '17 at 13:35

3 Answers3

30

In Java, the class system is a way to group similar objects. An instance of a class is an individual object which belongs to that class.

In Haskell, the class system is (roughly speaking) a way to group similar types. (This is the reason we call them "type classes"). An instance of a class is an individual type which belongs to that class. (That is, until you start considering multiparametric type classes).

Incidentally, a Haskell (monoparametric) class somewhat resembles a Java interface and, by extension, a Java class. Or perhaps a Haskell instance resembles Java class. It's better to view this as a coincidence. Approach the term keeping its mathematical origins in mind. A class is just a bunch of things that belong together, and an instance is one of these things.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
11

If you're interested in explanation of type classes and difference from Java interfaces you should read this post by <❤>. It also explains instances as well.

As for me, I look at instance as connection between data type and interface. data contains some information, class contains methods. data is about data (sorry for tautology) and class is about behavior. When you look at data type you don't see what you can do with it, instead you see what it stores. When you look at class you see what type should be able to do, you don't care what it stores internally. In real programming you actually care about details of implementations and how methods implemented using specific data. So instance just shows you relation between some data and some behavior — how this behavior implemented using given data.

In case you're interested more in model of type classes then read this blog post: http://www.haskellforall.com/2012/05/scrap-your-type-classes.html

You can look at instances as a values! It might blow your mind if you face such definition first time.

In some dependently type languages instances are really values that you can pass to other functions. Take a look at this question:

In Idris, is "Eq a" a type, and can I supply a value for it?

Shersh
  • 9,019
  • 3
  • 33
  • 61
4

it seems like instances are types (like ShirtSize) which you can apply type-class functions on (e.g the (==) function from MyEq)

Absolutely correct.

In Haskell a type is a defined structure of data. Every value that exists in Haskell code has a defined type. And a type can be made an instance of a class, which means... actually, hold that thought. I want to talk about functions.

Functions have type signatures, defining which type(s) they can be used on. If a function is defined to work on a particular type, then the function can be used on any value that has that type. If a function is defined to work on a particular class, then it can be used on any value of any of the types that are instances of that class.

When you define a class you describe some minimal set of functions (eg == in your example) which have to be implemented for all the types that want to be instances of that class. The class defines names and signatures for those functions, and that definition means those names and signatures are fixed. They will be the same for every instance of the class.

But the implementations aren't fixed by the class. They can be different for different types. We make a type into an instance of a class by writing an instance statement, in which we can define how those functions will work. If the class provides a default implementation of a function, then the different instance types can override the default and have their own definitions. And if there is no default, then the instance types must have their own definitions.

Now you have a minimal set of functions which can be called with any value of any of the types. And you can write more functions that work by calling those functions, and build up from there.

The idea is really useful, but IMHO the terminology is awful. Saying that these types are instances of a class makes it sound as if they're subtypes or child types, inheriting properties from parent types. But it's not like that at all. Being an instance of a class is like being a member of a club. Lots of different, unrelated types can all be instances of the same class. And one type can be an instance of lots of different unrelated classes, all at the same time.

In Rust, they have the same idea, but with the word 'trait' instead of 'class'. Instead of saying "this type is an instance of that class", they would say "this type implements that trait". I think that gets the idea across much better.