如果类型是 HList 的成员,我如何检查无形?
How do I check in shapeless if a type is a member of an HList?
我正在对字符串执行一系列预处理步骤,我正在考虑使用 HList
s 来提高步骤的安全性。某些处理步骤必须在其他步骤之后 运行,所以我考虑在类型系统中对其进行编码。我的第一次尝试是:
trait Step
trait Raw extends Step
trait A extends Step
trait B extends Step
trait DependsOnA extends Step
trait DependsOnB extends Step
case class ToBeProcessed[S <: Step](value: String)
object ToBeProcessed {
def raw(input: String): ToBeProcessed[Raw] = ...
def doA(input: ToBeProcessed[Raw]): ToBeProcessed[A] = ...
def doB(input: ToBeProcessed[A]): ToBeProcessed[B] = ...
def doDependsOnA(input: ToBeProcessed[B]): ToBeProcessed[DependsOnA] = ...
def doDependsOnB(input: ToBeProcessed[DependsOnA]): ToBeProcessed[DependsOnB] = ...
}
这行得通,因为它迫使我按顺序调用所有内容 doA
> doB
> doDependsOnA
> doDependsOnB
,这是它可能的顺序有效,但是:
- 它在不依赖彼此的步骤之间强制依赖
- 如果我想实现一个新的中间步骤
doC
我必须改变与之无关的东西的类型
所以我开始阅读 Haskell 中有关类型级别列表的内容,并意识到我可以使用它来编码我的依赖项。所以我开始阅读有关 Shapeless HList
s 的文章,然后弹出:
case class ToBeProcessed[S <: HList](value: String)
object ToBeProcessed {
def raw(input: String): ToBeProcessed[Raw :: HNil] = ...
def doA[S <: HList](input: ToBeProcessed[S]): ToBeProcessed[A :: S] = ...
def doB[S <: HList](input: ToBeProcessed[S]): ToBeProcessed[B :: S] = ...
为了对依赖项进行编码,我必须有一种方法来检查 A 是否包含在给定的 HList 中:
def doDependsOnA[S <: HList, ???](input: ToBeProcessed[S]): ToBeProcessed[DependsOnA :: S] = ...
}
在 ???
类型中,我必须以某种方式编码 S
包含 A
。我仍然不确定该怎么做。这可能吗?
Shapeless 已经有一个类型类来证明 HList
包含特定类型:Selector
。你会像这样使用它:
import shapeless._, ops.hlist.Selector
def doDependsOnA[S <: HList](input: ToBeProcessed[S])(implicit ev: Selector[S,A]): ToBeProcessed[DependsOnA :: S] = ???
我正在对字符串执行一系列预处理步骤,我正在考虑使用 HList
s 来提高步骤的安全性。某些处理步骤必须在其他步骤之后 运行,所以我考虑在类型系统中对其进行编码。我的第一次尝试是:
trait Step
trait Raw extends Step
trait A extends Step
trait B extends Step
trait DependsOnA extends Step
trait DependsOnB extends Step
case class ToBeProcessed[S <: Step](value: String)
object ToBeProcessed {
def raw(input: String): ToBeProcessed[Raw] = ...
def doA(input: ToBeProcessed[Raw]): ToBeProcessed[A] = ...
def doB(input: ToBeProcessed[A]): ToBeProcessed[B] = ...
def doDependsOnA(input: ToBeProcessed[B]): ToBeProcessed[DependsOnA] = ...
def doDependsOnB(input: ToBeProcessed[DependsOnA]): ToBeProcessed[DependsOnB] = ...
}
这行得通,因为它迫使我按顺序调用所有内容 doA
> doB
> doDependsOnA
> doDependsOnB
,这是它可能的顺序有效,但是:
- 它在不依赖彼此的步骤之间强制依赖
- 如果我想实现一个新的中间步骤
doC
我必须改变与之无关的东西的类型
所以我开始阅读 Haskell 中有关类型级别列表的内容,并意识到我可以使用它来编码我的依赖项。所以我开始阅读有关 Shapeless HList
s 的文章,然后弹出:
case class ToBeProcessed[S <: HList](value: String)
object ToBeProcessed {
def raw(input: String): ToBeProcessed[Raw :: HNil] = ...
def doA[S <: HList](input: ToBeProcessed[S]): ToBeProcessed[A :: S] = ...
def doB[S <: HList](input: ToBeProcessed[S]): ToBeProcessed[B :: S] = ...
为了对依赖项进行编码,我必须有一种方法来检查 A 是否包含在给定的 HList 中:
def doDependsOnA[S <: HList, ???](input: ToBeProcessed[S]): ToBeProcessed[DependsOnA :: S] = ...
}
在 ???
类型中,我必须以某种方式编码 S
包含 A
。我仍然不确定该怎么做。这可能吗?
Shapeless 已经有一个类型类来证明 HList
包含特定类型:Selector
。你会像这样使用它:
import shapeless._, ops.hlist.Selector
def doDependsOnA[S <: HList](input: ToBeProcessed[S])(implicit ev: Selector[S,A]): ToBeProcessed[DependsOnA :: S] = ???