Hi,
I am wondering if it is possible to use the Scala type system to have “lego brick” type blocks that I can chain together, with the compiler checking that the blocks fit together? The main thing I would like to have is the type computed from the value of one of the members of the class. I can do this with an implicit conversion to a “typed” class, but this happens at runtime which is not really what I am looking for. From a bit of research, I think this may be “dependent typing”, which it seems Scala supports in some form, but I am not sure if what I want is possible.
Here is a minimal example which illustrates what I am after:
trait TypedBlock
case class TypedBlock_1() extends TypedBlock
case class TypedBlock_2() extends TypedBlock
def modelToTypedBlock(x: Block): TypedBlock = x.layers.headOption match
case Some(Layer(1)) => TypedBlock_1()
case Some(Layer(2)) => TypedBlock_2()
case class Layer(in: Int)
class Block(val layers: Seq[Layer])
class MyValidBlock() extends Block(List(
Layer(1),
Layer(2)))
class MyInvalidBlock() extends Block(List(
Layer(3),
Layer(2)))
object Conversions:
given model2TypedBlock: Conversion[Block, TypedBlock] =
modelToTypedBlock(_)
end Conversions
@main def example: Unit = {
import Conversions.model2TypedBlock
val myValidBlock = MyValidBlock()
val myTypedValidBlock: TypedBlock = myValidBlock
println(s"myTypedValidBlock: $myTypedValidBlock")
val myInvalidBlock = MyInvalidBlock()
val myTypedInvalidBlock: TypedBlock = myInvalidBlock
println(s"myTypedInvalidBlock: $myTypedInvalidBlock")
}
This succeeds at compile time but throws an error at runtime. Is there a way to change this so that the conversion happens at compile time and throws an error then?
From a bit of research, I think this kind of thing is possible in F sharp, using the DependentTypes library so I was hoping I could do the same in Scala.