管道依赖的类型级定义
Type level definition of pipeline dependency
我想构建一个管道依赖关系,其中 2nd 级别取决于 1st 一个,3rd 取决于 2nd AND 1st 等等…
我已经定义了这样的结构
trait Level[A <: Level[A]] {
type DependsOn <: Level[DependsOn]
val previousDependencies: List[DependsOn]
}
trait First extends Level[First] {
type DependsOn = Nothing
}
trait Second extends Level[Second] {
type DependsOn = First
}
class FirstLevel extends First {
val previousDependencies = List.empty
}
class SecondLevel(val previousDependencies: List[FirstLevel]) extends Second
到目前为止一切正常。但我无法让它与依赖于前两个结构的第三个结构一起工作。我试过 shapeless Product
和 Coproduct
但我无法让它正常工作。我知道它必须是一个 Product
意思和类型,它意味着使用无形 HList
。请帮助:)
您可以将 Shapeless' heterogenous lists (HList) 与更多自定义的自制 HList 一起使用。我会选择前者,因为它会更清晰、更容易理解。下面代码中的主要思想是,您将关卡的类型链与所有元素类型的 "accumulated" 类型保持在一起。
import shapeless.{HNil, HList}
sealed trait Level[MyElement] {
type Previous <: Level[_]
type MyList <: HList
def elements: MyList
}
trait LNil extends Level[Nothing] {
type MyElement = Nothing
type MyList = HNil
}
trait LCons[MyElement] <: Level[MyElement] {
type MyList = shapeless.::[List[MyElement], Previous#MyList]
}
如您所见,MyList 包含来自以下级别的所有元素类型的 HList。现在我们可以提供更少的抽象实现,从而可以轻松构建此类关卡:
object ConcreteLNil extends LNil {
def elements = HNil
}
class ConcreteLCons[MyElement, PreviousList <: Level[_]]
(thisElems: List[MyElement], val previous: PreviousList)
extends LCons[MyElement] {
type Previous = PreviousList
type MyElement = String
def elements = thisElems :: previous.elements
}
您现在可以像这样使用它了:
val first = new ConcreteLCons(1 :: 2 :: Nil, ConcreteLNil)
val second = new ConcreteLCons("x" :: "y" :: Nil, first)
val third = new ConcreteLCons(1.0 :: Nil, second)
third.elements
// List(1.0) :: List(x, y) :: List(1, 2) :: HNil
我想构建一个管道依赖关系,其中 2nd 级别取决于 1st 一个,3rd 取决于 2nd AND 1st 等等…
我已经定义了这样的结构
trait Level[A <: Level[A]] {
type DependsOn <: Level[DependsOn]
val previousDependencies: List[DependsOn]
}
trait First extends Level[First] {
type DependsOn = Nothing
}
trait Second extends Level[Second] {
type DependsOn = First
}
class FirstLevel extends First {
val previousDependencies = List.empty
}
class SecondLevel(val previousDependencies: List[FirstLevel]) extends Second
到目前为止一切正常。但我无法让它与依赖于前两个结构的第三个结构一起工作。我试过 shapeless Product
和 Coproduct
但我无法让它正常工作。我知道它必须是一个 Product
意思和类型,它意味着使用无形 HList
。请帮助:)
您可以将 Shapeless' heterogenous lists (HList) 与更多自定义的自制 HList 一起使用。我会选择前者,因为它会更清晰、更容易理解。下面代码中的主要思想是,您将关卡的类型链与所有元素类型的 "accumulated" 类型保持在一起。
import shapeless.{HNil, HList}
sealed trait Level[MyElement] {
type Previous <: Level[_]
type MyList <: HList
def elements: MyList
}
trait LNil extends Level[Nothing] {
type MyElement = Nothing
type MyList = HNil
}
trait LCons[MyElement] <: Level[MyElement] {
type MyList = shapeless.::[List[MyElement], Previous#MyList]
}
如您所见,MyList 包含来自以下级别的所有元素类型的 HList。现在我们可以提供更少的抽象实现,从而可以轻松构建此类关卡:
object ConcreteLNil extends LNil {
def elements = HNil
}
class ConcreteLCons[MyElement, PreviousList <: Level[_]]
(thisElems: List[MyElement], val previous: PreviousList)
extends LCons[MyElement] {
type Previous = PreviousList
type MyElement = String
def elements = thisElems :: previous.elements
}
您现在可以像这样使用它了:
val first = new ConcreteLCons(1 :: 2 :: Nil, ConcreteLNil)
val second = new ConcreteLCons("x" :: "y" :: Nil, first)
val third = new ConcreteLCons(1.0 :: Nil, second)
third.elements
// List(1.0) :: List(x, y) :: List(1, 2) :: HNil