Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala type system, constrain member's type by parameter of own type

Tags:

types

scala

Not really sure the standard terminology here, so I'll try to describe what I'm trying to do. In case you're curious, the app I'm actually trying to write is an asynchronous task queue similar to Resque or rq.

I have a type TaskDef[ArgsT <: AnyVal, ResultT <: AnyVal]. In case you're curious, TaskDef represents "how to execute an asynchronous task which takes argument type ArgsT and result type ResultT, or, the code behind a task".

I'm trying to define a type TaskInst[DefT <: TaskDef]. In case you're curious, TaskInst represents "a TaskDef and associated argument to run it with, or, an actual task instance being submitted to the queue". TaskInst has two members, definition: DefT and arguments whose type I cannot write in code.

In English, my desired constraint is: "For a given DefT, where DefT is some TaskDef[ArgsT, ResultT], TaskInst[DefT] should contain a DefT and an ArgsT". That is, the argument type of the task definition should match the type of the argument given to the task.

How do I express this in the Scala type system?

Alternatively, am I modeling my domain incorrectly and attempting to do something un-idiomatic? Would some alternative approach be more idiomatic?

Thanks in advance!

EDIT:

I think my historical self writing Java would probably have resorted to unchecked casts at this point. This is definitely feasible with some amount of unchecked casts and just leaving out the constraint between the type of the TaskInst's arguments vs the type of the embedded TaskDef's arguments. But, I do wonder whether this is something the compiler can enforce, and hopefully without too scary a syntax.

like image 833
Ming Avatar asked Nov 18 '25 18:11

Ming


1 Answers

Define them as abstract types:

trait TaskDef {
    type Arguments <: AnyVal
    type Result <: AnyVal
}

Then use a type projection:

trait TaskInst[DefT <: TaskDef] {
    def definition: DefT
    def arguments: DefT#Arguments
}

Live Demo


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!