milessabin/shapeless — pull request #55 by larsrh (2013-10-19 16:40:44+00:00)
Title: Type Class Derivation: Don't use ??? for TC[CNil]

Previous behaviour was unsound when the `TypeClass` instance always used both arguments eagerly.

Consider an example derivation of an instance for `Int :+: String :+: CNil`.

Previously:

```scala
TC.coproduct(intInstance, TC.coproduct(stringInstance, ???))
```

Type classes which "consume" data are unproblematic: There will never be a value of type `CNil`, hence the `???` is never executed. On the other hand, type classes which "produce" data, e.g. `Arbitrary`, would certainly want to
produce something for both cases.

The fix is conceptually simple. We introduce a new method on `TypeClass` called `coproduct1` which simply maps an instance for type `T` into type `T :+: CNil`.

Now:

```scala
TC.coproduct(intInstance, TC.coproduct1(stringInstance))
```

Users don't have to change anything, as there is a default implementation for `coproduct1` (admittedly, not very efficient: it uses `project` internally).