2017-02-10 55 views
3

我正在对字符串进行一系列预处理步骤,我正在考虑使用HList来提高步骤的安全性。某些处理步骤必须在其他处理步骤之后运行,所以我正在考虑在类型系统中对其进行编码。我的第一个尝试是:如果某个类型是HList的成员,我该如何检查无形?

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中的类型级别列表,并意识到我可以使用它来编码我的依赖关系。于是,我开始阅读关于无形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] = ... 

而且编码的依赖,我必须有办法检查一个被包含在一个给定的HList:

def doDependsOnA[S <: HList, ???](input: ToBeProcessed[S]): ToBeProcessed[DependsOnA :: S] = ... 

} 

其中类型I的???必须以某种方式编码S包含A。我仍然不确定我该怎么做。这可能吗?

回答

2

无形状已经有一个typeclass用于证明HList包含某种类型:Selector。你会这样使用它:

import shapeless._, ops.hlist.Selector 

def doDependsOnA[S <: HList](input: ToBeProcessed[S])(implicit ev: Selector[S,A]): ToBeProcessed[DependsOnA :: S] = ??? 
+0

美丽!谢谢一堆。我今天早些时候正在研究不成形的代码寻找它,但没有偶然发现这一点。 –

相关问题