Support for type classes

In some languages it is possible to specify, for example in the type signature of a function, that any type is valid as long as it conforms to a contract. Sometimes it is called a type class.

This is already possible to specify with dry-types by hand. For example, this is a type for anything that responds to #call:

Foo = Types.Constructor(Types::Nominal::Any) do |v|
  if v.respond_to?(:call)
    raise NoMethodError

What do you think about supporting it in a native way? Something like:

Foo = Types.Contract([:call]) # For anything responding to #call
Foo = Types.Contract(SomeClass, [:call]) # For any children instance of `SomeClass` responding to #call

I’m interested in the first example, but supporting the second one would make it more complete.

Other possible names would be Types.Class or Type.Duck, I don’t mind which name :slight_smile:

1 Like

I like this idea. It should be very simple to do given that all the building blocks are in place. WDYT @flash-gordon & @timriley :question:

Something like this would be fine to add I reckon.

I wonder whether it should be a top-level thing like this “Types.Contract” idea, or whether it should actually be a constraint, e.g. Types::Any.constrained(respond_to?: [:call])

The latter. Types.Contract would be just a convenient type builder, like we have Types.Constructor etc. this would require adding respond_to? predicate to dry-logic too.