簡體   English   中英

Scala類型系統,通過自有類型的參數約束成員的類型

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

這里不太確定標准術語,所以我會試着描述我想要做的事情。 如果您感到好奇,我實際上嘗試編寫的應用程序是一個類似於Resque或rq的異步任務隊列。

我有一個類型TaskDef[ArgsT <: AnyVal, ResultT <: AnyVal] 如果你很好奇, TaskDef代表“如何執行一個異步任務,它接受參數類型ArgsT和結果類型ResultT ,或者任務背后的代碼”。

我正在嘗試定義一個類型TaskInst[DefT <: TaskDef] 如果你很好奇, TaskInst代表“一個TaskDef和相關的參數來運行它,或者,一個實際的任務實例被提交到隊列”。 TaskInst有兩個成員, definition: DefT和我不能在代碼中寫入的類型的arguments

在英語中,我期望的約束是:“對於給定的DefT ,其中DefT是一些TaskDef[ArgsT, ResultT]TaskInst[DefT]應該包含DefTArgsT ”。 也就是說,任務定義的參數類型應該與給予任務的參數類型相匹配。

如何在Scala類型系統中表達這一點?

或者,我是否錯誤地為我的域建模並嘗試做一些非慣用的事情? 一些替代方法會更加慣用嗎?

提前致謝!

編輯:

我認為我的歷史自我寫作Java可能會在這一點上使用未經檢查的演員表。 對於一些未經檢查的強制轉換,這肯定是可行的,只是省略了TaskInst參數類型與嵌入式TaskDef參數類型之間的約束。 但是,我確實想知道這是否是編譯器可以強制執行的,並且希望沒有太可怕的語法。

將它們定義為抽象類型:

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

然后使用類型投影:

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

現場演示

@rightfold給出的答案的附加內容:

如果您希望始終使用類型參數,則需要將類型參數正確傳遞給類型構造函數。

對不起,我這樣說有點含糊不清,所以讓我用我當前的代碼作為一個具體的例子。

trait TaskDef[ArgT_, ResT_] {
  type ArgT = ArgT_
  type ResT = ResT_
  val name: String
  def exec(arg: ArgT): String \/ ResT
}

class TaskInst[ArgT, ResT, DefT <: TaskDef[ArgT, ResT]] (
  val id: UUID,
  val defn: DefT,
  val arg: ArgT
)

我當前代碼與@ rightfold示例的主要TaskDef在於TaskDef采用類型參數。 然后,當TaskInst的聲明引用TaskDef ,它必須為類型構造函數提供適當的類型。

我最初錯誤地傳遞了占位符。 也就是說,我正在編寫class TaskInst[DefT <: TaskDef[_, _] 事實證明,這並不意味着我的意思。 (我不知道。也許其他人可能傾向於遵循同樣的思路。所以,這只是一個警告而不是。)不要這樣做,因為那時scalac會將預期解釋為生成的占位符(正如您可能想象的那樣,沒有任何內容匹配),然后您會得到如下所示的模糊錯誤消息。

[error] /Users/mingp/Code/scala-redis-queue/src/main/scala/io/mingp/srq/core/TaskInst.scala:8: type mismatch;
[error]  found   : TaskInst.this.arg.type (with underlying type _$1)
[error]  required: _$1
[error]   val arg: DefT#ArgT_
[error]       ^
[error] one error found

只是張貼這個,希望未來的讀者不會陷入我所做的同一個洞。

編輯:

作為進一步的補充,既然我已經嘗試了一天,我的印象是這對於異步任務來說實際上並不是一個好的數據模型。 你最好合並,因為TaskDef的獨立實例並不真正有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM