【问题标题】:How do I check in shapeless if a type is a member of an HList?如果类型是 HList 的成员,我如何检查 shapeless?
【发布时间】:2017-02-13 07:17:43
【问题描述】:

我正在对字符串执行一系列预处理步骤,并且正在考虑使用HLists 来提高我的步骤的安全性。一些处理步骤必须在其他处理步骤之后运行,所以我正在考虑在类型系统中对其进行编码。我的第一次尝试是:

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 的顺序调用所有内容,这是它工作的可能顺序,但是:

  1. 它在不相互依赖的步骤之间强制依赖
  2. 如果我想实现一个新的中间步骤doC,我必须更改与它无关的事物的类型

所以我开始阅读 Haskell 中的类型级别列表,并意识到我可以使用它来编码我的依赖项。所以我开始阅读 Shapeless HLists 并弹出以下内容:

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。我仍然不确定我该怎么做。这可能吗?

【问题讨论】:

    标签: scala shapeless type-level-computation


    【解决方案1】:

    Shapeless 已经有一个类型类来证明HList 包含特定类型:Selector。你可以这样使用它:

    import shapeless._, ops.hlist.Selector
    
    def doDependsOnA[S <: HList](input: ToBeProcessed[S])(implicit ev: Selector[S,A]): ToBeProcessed[DependsOnA :: S] = ???
    

    【讨论】:

    • 漂亮!谢谢一堆。我今天早些时候正在研究无形的代码寻找它,但没有偶然发现。
    猜你喜欢
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多