Type Classes

A type class is a special pseudo-type that can be used to match against types in the context of overload resolution or the is operator. Nim supports the following built-in type classes:

type classmatches
objectany object type
tupleany tuple type
enumany enumeration
procany proc type
refany ref type
ptrany ptr type
varany var type
distinctany distinct type
arrayany array type
setany set type
seqany seq type
autoany type
anydistinct auto (see below)

Furthermore, every generic type automatically creates a type class of the same name that will match any instantiation of the generic type.

Type classes can be combined using the standard boolean operators to form more complex type classes:

  1. # create a type class that will match all tuple and object types
  2. type RecordType = tuple or object
  3. proc printFields[T: RecordType](rec: T) =
  4. for key, value in fieldPairs(rec):
  5. echo key, " = ", value

Whilst the syntax of type classes appears to resemble that of ADTs/algebraic data types in ML-like languages, it should be understood that type classes are static constraints to be enforced at type instantiations. Type classes are not really types in themselves, but are instead a system of providing generic “checks” that ultimately resolve to some singular type. Type classes do not allow for runtime type dynamism, unlike object variants or methods.

As an example, the following would not compile:

  1. type TypeClass = int | string
  2. var foo: TypeClass = 2 # foo's type is resolved to an int here
  3. foo = "this will fail" # error here, because foo is an int

Nim allows for type classes and regular types to be specified as type constraints of the generic type parameter:

  1. proc onlyIntOrString[T: int|string](x, y: T) = discard
  2. onlyIntOrString(450, 616) # valid
  3. onlyIntOrString(5.0, 0.0) # type mismatch
  4. onlyIntOrString("xy", 50) # invalid as 'T' cannot be both at the same time