I would like to do the following somehow and wonder how far I can get with Scala:
trait Generator[A] {
def generate(): LazyList[A]
}
trait RandomGenerator[T] extends Generator[T]
trait OrderedGenerator[T] extends Generator[T]{
val size: Int
}
class TransformGenerator[T, R, G[A] <: Generator[A]](
private val gt: G[T],
private val transform: (T) => R
) extends G[R] { // G[R] is not a type class, => maybe somehow possible with a macro, generating a class on the fly?
// double definition, I don't know how to say all but generate or another way so that generate below takes precedence
export gt.*;
override def generate(): LazyList[R] = gt.generate().map(transform)
}
1 Like
This gives me flashbacks to writing C++ template class definitions, which did allow precisely this - and a whole lot of really messy error messages and subtle issues about duplication of compiled code segments into the bargain. 
Sorry, I canāt answer your question, but let me ask you this anyway: when writing in Java, C#, F# and Scala, none of which allow this kind of āgeneric boilerplate API inheritanceā, Iāve never felt the lack of this capability.
If you have your TransformGenerator
extend Generator[R]
, then isnāt that enough for client code to use it?
I see you are already allowing flexibility in the underlying generation method by delegating to an existing core generator implementation and transforming that.
(You could btw just treat that transform as a map operation method in the Generator
API. This is what Scalacheck and Americium do.)
Anyway, some inspiration here: americium/src/main/scala/com/sageserpent/americium/Trials.scala at 292e5ad3b082211c7d124061f23a4e69ad5b509c Ā· sageserpent-open/americium Ā· GitHub
Have a look around to see how it works under the bonnet. I wrote some design notes too: Design and Implementation Ā· sageserpent-open/americium Wiki Ā· GitHub
Hope this is useful in some way.
EDIT: I forgot to ask, was an LLM involved on writing this? Indulge me, itās a phase Iām going through asking this question every now and thenā¦
Iād use inheritance for data and intrinsic functionality and otherwise use typeclasses. The un-nice thing about typeclasses is that you have more boilerplate, but the nice thing is that you can resolve ānotā-style relationships as part of context parameter resolution, so you can have āforward everything exceptā by writing only the āexceptā error instead of manually forwarding everything else.
Hereās a runnable example: Scastie - An interactive playground for Scala.
@sageserpent-open No, not even considered to use an LLM for this question as I doubt it would give me good answers. Right, in C++ it would be possible but I am also happy to do without the cryptic error messages
Thanks for the link, Iāll check it out. I already provide map
, filter
and co. I write the whole thing in Kotlin and from time to time I wonder if using Scala would allow me to reduce more code duplication. So in this case I was wondering if I can reduce 3 tiny classes to one which basically do the same. I am not proficient in writing macros nor typeclasses and was curiousā¦
@Ichoran thanks for your example, I wasnāt aware of that typeclasses allow to define such not-style relationships
For this particular case (like export all but⦠) it seems overly involved to me, maybe worth adding something to the export clause construct. Or allow that an override
in the class takes precedence but thatās more for the contributors forum I guess.