Hi Muniverse, apologies for the delay, yesterday was our Seattle office party and I didn’t have as much time to try out the Traverse solution that Juan Pedro suggested. I’ve implemented a traverse function for ProtobufF and still run into the stack overflow error. (I also tried the @deriveTraverse
annotation, which is way cool! But it also resulted in the stack overflow.) I’m analyzing the difference between the code that Juan Pedro suggested in my minimal repro app and the actual code and 1 big thing sticks out as a problem.
In the Skeuomorph code, TRepeated is constructed with a value of type A. This makes sense, TRepeated should contain some type which repeats, which could be another Message or just a primitive type, like a String.
Here’s a loose representation of the structure we have:
`BaseDescriptor` ==========(Coalgebra)==========> `ProtobufF[A]`
||
||
(is parent of)
||
\/
`FieldDescriptor` ====(Branch of match statement)===> `TRepeated[A](value: A)` AND Some primitive like `TString[A]()`
So in effect we have one source type, FieldDescriptor
that needs to be used to generate a TRepeated(fieldDescriptor)
and the primitive corresponding to its type, i.e. TString()
I’m fairly confident this is the source of the non terminating loop in my code, and I’m not sure how to fix this.
- This is what would represent a List[SomeType] in Scala code generation, so we probably can’t leave the code as is, downgrading everything to a non-list type.
- Remove TRepeated as a class altogether and instead represent whether a field can be repeated on the primitive (leaf) nodes of the ProtobufF ADT. This would, however, push the responsibility of printing whether a type is a scala List to all the corresponding leaf nodes in the MuF ADT.
- Remove TRepeated as a class and represent whether a field can be repeated as a boolean on the Field class. This would also change MuF’s Field class and the printing syntax, which might break our existing Avro implementation.
- Some sort of depth counter for the transformation from a BaseDescriptor to a ProtobufF so we can conditionally decide which class to transform our FieldDescriptor into.
- Some other thing?
- Let's say we can't directly read a
FieldDescriptor
into two types:TRepeated
and the primtive types likeTString
. Maybe that's not how our domain can be modeled given the constraints, but that is ok, because we do have the ability to provide micro-optimizations when operating in MuF (or ProtobufF for that matter.) Perhaps we can provide a natural transformation from MuF ~> MuF or ProtobuF ~> ProtobufF such that we can still get the desired String representation of the repeated field.
Anyways, sorry for the novel. Thanks for reading!