And then you have typeclasses, which is basically a class (absolutely nothing to do with OOP classes in C/C++ or Java or similar languages) to which types may belong, and the typeclass defines certain behaviors that types belonging to it will exhibit.
For instance, in the standard library,
Eq is a typeclass, and the behavior that
Eq defines is that two values can be “
equated”, whatever the meaning of
equating two values of a type may mean.
Int is a type. Since
Int belongs to
Eq, it means that all values of
Int (e.g. 100, 423, -200, etc) have a meaning when they are
equated. This meaning is familiar to all of us,
100 == 100 is true, but
100 == 423 is not.
The manner in which typeclasses define behaviors, is through a set of one or more functions that the typeclass defines, that all members of the typeclass must implement.
For instance, in our venerable
Eq typeclass, the operators (which are functions)
/= are defined. Hence all members of the
Eq typeclass must be able to be
And now let’s make a typeclass for our strings:
class ReturnSame a where returnSame :: a -> a
This is a rather useless typeclass, and the behavior is that any member of which must implement returnSame. As the name suggests, we are going to return exactly what we get, and just that. Note that “a” here is similar to the above, it’s a type variable. In this case, it represents the instance that we are going to create, and how that instance behaves/is used. To make that clearer, let’s use an example.
Let’s make our StringString and StringAnything instances of the typeclass:
instance BecomesFalse StringString where turnToFalse x = x instance BecomesFalse (StringAnything a) where turnToFalse x = x
Let’s play with it:
turnToFalse (StringString "John" "Peter") ==> StringString "John" "Peter" :t turnToFalse (StringString "John" "Peter") ==> StringString turnToFalse (StringAnything "John" ["Peter"]) ==> StringAnything "John" ["Peter"] :t turnToFalse (StringAnything "John" ["Peter"]) ==> StringAnything [[Char]]
There we go, we have our own type, and our own typeclass.
Understanding the Haskell type system goes a long way, and this is just touching on the tip of the iceberg. Hence, this is not meant to be an utterly complete and formal introduction to typeclasses, or types. For that, there are great resources out there. This is one of them. There are also missing bits, such as type subclasses (type constraints), and so on.
Once again, remember:
Value constructors are functions, and they take parameters, and produce a value
You cannot write
StringAnything Int, in code, that’s a type constructor. You can only write
StringAnything 4, that’s a value constructor.
The value has a type, and is defined by the type constructor
Type constructors that have no variables are concrete types by themselves (e.g.
Type constructors that have variables are polymorphic types, and are not types by themselves (e.g.
For these, you have to give the variable a value (a concrete type), and then the type constructor creates a concrete type (e.g.