Hello everyone,
I’m trying to design a Scala library and would like to perform the following:
- Define custom types where each custom type has a corresponding Scala host type (e.g.,
MyClass1
is a custom type that has a host typeBigInt
) - Define literal types for the custom types that has a member variable of the host type (
MyLiteral[MyClass1]
'svalue
is ofBigInt
type) - Enable the user to define compositions of my custom types which also has a literal type. We want each field to have a value of the corresponding host type (e.g.,
MyLiteral[MyComposition]
should have two fieldsa: BigInt
andb: String
) - The composed types can be nested
object Main:
///////////////////////////////////////////////////////////////////////////////
// Library code
//////////////////////////////////////////////////////////////////////////////
// We want to define custom types that corresponds to some native Scala type
// BaseType: Base type for our custom types
// HostType: Corresponding scala native type
trait BaseType:
type HostType
def cloneType: BaseType
def getLit(value: HostType): MyLiteral[_]
class MyClass1(val w: Int) extends BaseType:
type HostType = BigInt
def cloneType: MyClass1 = new MyClass1(this.w)
def getLit(value: HostType) = new MyLiteral[MyClass1](this.cloneType, value)
class MyClass2(val w: Int) extends BaseType:
type HostType = String
def cloneType: MyClass2 = new MyClass2(w)
def getLit(value: HostType) = new MyLiteral[MyClass2](this.cloneType, value)
// For each of our custom types, we want to define a literal of that type
class MyLiteral[T <: BaseType](val basetype: T, val value: basetype.HostType)
abstract class Composition extends reflect.Selectable with BaseType
///////////////////////////////////////////////////////////////////////////////
// User APIs
//////////////////////////////////////////////////////////////////////////////
// We would also like to compose out custom types.
// And the composed types should also have a literal value corresponding to it.
class MyComposition(w1: Int, w2: Int) extends Composition:
val a = MyClass1(w1)
val b = MyClass2(w2)
// Question 1. We would like the derive these three functions for the subclasses of "Composition".
// The subclasses can be nested within each other as well.
type HostType = Record { val a: BigInt; val b: String }
def getLit(value: HostType) = new MyLiteral[MyComposition](this.cloneType, value)
def cloneType: MyComposition = new MyComposition(w1, w2)
val class1 = MyClass1(3)
val class1Literal = class1.getLit(BigInt(10))
val comp = MyComposition(2, 3)
// Question 2. We would like to set the literals with a API that looks like the commented line below
// val compLit = comp.getLit(a = BigInt(1), b = "hello")
My question is:
- Is there a way of synthesizing the
HostType
for any user defined composition of my custom types using Macros/reflection? - Is there a better way of defining
getLit
in such a way that we can assign values to each field (e.g.,val compLit = comp.getLit(a = BigInt(1), b = "hello")
)?
We are open to using case class
for compositions instead of reflect.Selectable
for the composed types as well.