[英]Scala context bounds
在Scala中使用上下文范圍,您可以執行以下操作
trait HasBuild[T] {
def build(buildable: T): Something
}
object Builders {
implict object IntBuilder extends HasBuild[Int] {
override def build(i: Int) = ??? // Construct a Something however appropriate
}
}
import Builders._
def foo[T: HasBuild](input: T): Something = implicitly[HasBuild[T]].build(1)
val somethingFormInt = foo(1)
或者簡單地
val somethingFromInt = implicitly[HasBuild[Int]].build(1)
如何在范圍內具有適當的隱式HasBuild
對象的任何元素的Seq
類型? 如果沒有太多的魔術和外部庫,這可能嗎?
Seq[WhatTypeGoesHere]
-我應該能夠為每個元素找到合適的HasBuild
這顯然不能編譯:
val buildables: Seq[_: HasBuild] = ???
基本上,我希望能夠以一種通用的方式(例如:構建)處理不相關的類型,而無需用戶手動將它們包裝在某種適配器中,並由編譯器強制執行,這些類型實際上可以被處理。 不知道目的是否明確。
您可以執行的操作:
case class HasHasBuild[A](value: A)(implicit val ev: HasBuild[A])
object HasHasBuild {
implicit def removeEvidence[A](x: HasHasBuild[A]): A = x.value
implicit def addEvidence[A: HasBuild](x: A): HasHasBuild[A] = HasHasBuild(x)
}
現在(假設您添加了一個HasBuild[String]
進行演示):
val buildables: Seq[HasHasBuild[_]] = Seq(1, "a")
編譯,但是
val buildables1: Seq[HasHasBuild[_]] = Seq(1, "a", 1.0)
沒有。 只有HasHasBuild
時,可以使用帶有隱式HasBuild
參數的方法:
def foo1[A](x: HasHasBuild[A]) = {
import x.ev // now you have an implicit HasBuild[A] in scope
foo(x.value)
}
val somethings: Seq[Something] = buildables.map(foo1(_))
首先,與某些評論相反,您所依賴的是上下文范圍。 為T
請求隱式類型類實例就是您所說的“上下文綁定”。
您想要的是可以實現的,但並非無關緊要的,而且當然沒有其他庫也不是沒有。
import shapeless.ops.hlist.ToList
import shapeless._
import shapeless.poly_
object builder extends Poly1 {
implicit def caseGeneric[T : HasBuilder] = {
at[T](obj => implicitly[HasBuilder[T]].build(obj))
}
}
class Builder[L <: HList](mappings: L) {
def build[HL <: HList]()(
implicit fn: Mapper.Aux[builder.type, L, HL],
lister: ToList[Something]
) = lister(mappings map fn)
def and[T : HasBuilder](el: T) = new Builder[T :: L](el :: mappings)
}
object Builder {
def apply[T : HasBuilder](el: T) = new Builder(el :: HNil)
}
現在您可以執行以下操作:
Builder(5).and("string").build()
這將召喚出build
從所有個體implcit類型類實例的方法,給你的結果,其中每個結果類型的列表Something
。 它基於所有構建方法都具有Something
的下限的事實,例如,按照您的示例:
trait HasBuild[T] {
def build(buildable: T): Something
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.