Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type classes in Nim

I am trying to make a simple use of typeclasses in Nim. Please, keep in mind that I only have been using Nim since this morning, so I may have been doing something stupid.

Anyway, I would like to define a pseudorandom generator that produces a stream of values of type T. Sometimes T is numeric, hence it makes sense to know something about the minimum and maximum values attainable - say to rescale the values. Here are my types

type
  Generator*[T] = generic x
    next(var x) is T

  BoundedGenerator*[T] = generic x
    x is Generator[T]
    min(x) is T
    max(x) is T

I also have such an instance, say LinearCongruentialGenerator.

Say I want to use this to define Uniform generator that produces float values in an interval. I have tried

type Uniform* = object
  gen: BoundedGenerator[int]
  min_p: float
  max_p: float

proc create*(gen: BoundedGenerator[int], min: float, max: float): Uniform =
  return Uniform(gen: gen, min_p: min, max_p: max)

I omit the obvious definitions of next, min and max.

The above, however, does not compile, due to Error: 'BoundedGenerator' is not a concrete type

If I explicitly put LinearCongruentialGenerator in place of BoundedGenerator[int], everyting compiles, but of course I want to be able to switch more sophisticated generators.

Can anyone help me understand the compiler error?

like image 758
Andrea Avatar asked Jan 14 '15 17:01

Andrea


1 Answers

The type classes in Nim are not used to create abstract polymorphic types as it is the case with Haskell's type classes and C++'s interfaces. Instead, they are much more similar to the concepts proposal for C++. They define a set of arbitrary type requirements that can be used as overload-resolution criteria for generic functions.

If you want to work with abstract types, you can either define a type hierarchy with a common base type and use methods (which use multiple dispatch) or you can roll your own vtable-based solution. In the future, the user defined type classes will gain the ability to automatically convert the matched values to a different type (during overload resolution). This will make the vtable approach very easy to use as values of types with compatible interfaces will be convertible to a "fat pointer" carrying the vtable externally to the object (with the benefit that many pointers with different abstract types can be created for the same object). I'll be implementing these mechanisms in the next few months, hopefully before the 1.0 release.

Araq (the primary author of Nim) also has some plans for optimizing a certain type of group of closures bundled together to a cheaper representation, where the closure environment is shared between them and the end result is quite close to the traditional C++-like vtable-carrying object.

like image 113
zah Avatar answered Sep 29 '22 06:09

zah