improve error message when a label instance is not available - #44
Conversation
|
Larger issue I was confused why the original error is as bad as it is and why the type system does not catch the wrong second type, as both parameters are Tensor[T, V]. As far as I understand is it because of the covariance of Tensor: Because Tuple is a Parent type of all Tuples, e.g. Tuple1 <: Tuple and Tuple2 <: Tuple, the scala compiler find T==Tuple as a valid type for T, but then finds no Labels for Labels[Tuple], leading to the delayed and therefore confusing error message... Compromise? I did not find a good solution to fix this, while keeping covariance. Maybe covariance was added to quickly as I was not aware of this issue. So let's take a step back. What does covariance give us? It allows for such code: trait Parent derives Label
trait Child1 extends Parent derives Label
trait Child2 extends Parent derives Label
def concreteFunction(t: Tensor1[Parent, Float]): Tensor1[Parent, Float] = t + t // Parent is parameter type
val child1: Tensor1[Child1, Float] = Tensor(Shape1(Axis[Child1] -> 4)).fill(1f)
concreteFunction(child1) // we can call functio with Child typesHowever, this can also be implemented as: def concreteFunction2[C <: Parent](t: Tensor1[C, Float]): Tensor1[C, Float] = t + tWhich is even better as it preserves the Child type: The motivation to add covariance to Tensor's T was to allow "def concreteFunction" as this can be jit compiled, whereas concreteFunction2 must be compiled twice for Child1 and Child2 Generic type... An additional fact to consider is that the label and the type may differ if we have covariance. E.g., in concreteFunction, printing the tensor shape would print "child1", not "parent". While this makes sense to me, it could add confusion. Suggestion I suggest removing the T covariance from Tensor for now. Which leads to minor adjustments in some examples (but manageable). Then rethink your error message, probably one of the secarios is handled by the type system then... Related: I discovered something while investigating. We should allow this, which currently doesn't work.
This can be supported without Tensor Covariance (so is somewhat unrelated). It requires adjusting the binary operations: See https://github.com/benikm91/dimwit/tree/tensor-covariance for implementation. A real world example for this would be the mean and std in VariationalAutoEncoder - this is actually how I discoverd the problem: trait Latent derives Label
trait MeanLatent extends Latent derives Label
trait LogVarLatent extends Latent derives Label
val mean: Tensor1[MeanLatent, Float] = ???
val std: Tensor1[LogVarLatent, Float] = ???
val latent: Tensor1[Latent, Float] = (1f +! logVar - mean.pow(2f) - logVar.exp) // automatically change to latent parent type if two different childs are added.
println(latent.axes) // prints "latent" |
|
@benikm91 I think you meant message 1 not 2. I simplified the message. You can check if it makes sense for you and, if it does, merge it. |




Making mistakes with the labels can lead to nasty error messages in dimwit, which are extremely hard to pinpoint, as the resulting type is often computed and, thanks to type inference, not seen directly in the code.
As an example, consider the following code
Here, the user provides a covariance matrix to an independent normal distribution, instead of just the variances. From the error message it is almost impossible to infer the mistake.
Given really targeted error messages would require adding explicit checks to all sites where several labels are used (which seems impractical). This PR is a first attempt to provide at least a better general error message when something is wrong with the labels.