我正在嘗試使用許多不受約束的型別構建一個可以構建具有受約束型別的類的構建器。如何使用型別邊界的隱式證據來滿足型別約束?
例如說我想建立一個類:
class NameClass[N <: String](name: N)
我使用了一個看起來像這樣的構建器:
class NameClassBuilder[N](n: N) {
def name[NewN <: String](name: NewN) = new NameClassBuilder[NewN](name)
def build(implicit ev: N <:< String) : NameClass[N] = new NameClass[N](n)
}
object NameClassBuilder {
def builder : NameClassBuilder[Unit] = new NameClassBuilder[Unit]()
}
這個想法是您可以從一個虛擬型別/值開始,然后在添加欄位時更新型別。通過使用型別正確的證據,您只能在型別有意義時構建它。
問題是,它不會編譯,理由是,N從NameClassBuilder不滿足型別約束N <: String的NameClass,即使我已經包括證據表明它。
error: type arguments [N] do not conform to class NameClass's type parameter bounds [N <: String]
def build(implicit ev: N <:< String) : NameClass[N] = new NameClass[N](n)
有沒有辦法使用證據來滿足這個約束?
uj5u.com熱心網友回復:
你可以換回來NameClass[N with String]。N with String <: String對于任何N,如果真的N <: String那么N with String = N。在N <:< String你有build需要投n: N來N with String。
def build(implicit ev: N <:< String): NameClass[N with String] = {
type F[ X] = N with X
new NameClass(ev.liftCo[F](n))
}
Scastie 上的完整示例
uj5u.com熱心網友回復:
您是在告訴編譯器,在呼叫函式時build,應該存在符合N <:< String. 但在 的范圍內NameClassBuilder,N符合Any。
你可以試試:
class NameClassBuilder[N](n: N) {
def name[NewN <: String](name: NewN) = new NameClassBuilder[NewN](name)
def build[U <: String](implicit ev: N <:< String): NameClass[U] = new NameClass[U](n.asInstanceOf)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/384760.html
上一篇:scala模式匹配以洗掉某些情況
