对连续元素进行类型约束的列表
List with type constraints on consecutive elements
是否可以定义每对连续元素都满足某种关系(约束)的列表类型。例如,一个函数列表,这样的函数可以组成:
val f1: A => B = ???
val f2: B => C = ???
val f3: C => D = ???
type SafeList = ??? // how to define this?
val fs: SafeList = f1 :: f2 :: f3 :: HNil // OK
val fs: SafeList = f1 :: f3 :: HNil // ERROR
通常不可能使用类型别名来描述像这样有趣的约束——相反,您需要一个类型 class 来作为类型具有某些 属性.[=14= 的证据]
使用 Shapeless 通常可以使用库提供的类型 classes 来完成此操作,但我认为这里不是这种情况。幸运的是,自己编写并不太难:
import shapeless._
// Evidence that an hlist is made up of functions that can be composed.
trait Composable[L <: HList] {
type In
}
object Composable {
type Aux[L <: HList, In0] = Composable[L] { type In = In0 }
implicit def composable0[A, B]: Aux[(A => B) :: HNil, A] =
new Composable[(A => B) :: HNil] {
type In = A
}
implicit def composable1[A, B, T <: HList]
(implicit tc: Aux[T, B]): Aux[(A => B) :: T, A] =
new Composable[(A => B) :: T] {
type In = A
}
}
def composable[L <: HList: Composable] {}
我们在这里所做的是描述如何以单身人士 HList
作为基本案例,归纳地建立证据。在每一步,我们都使用 In
type 成员来跟踪下一个(即列表中较早的)函数的输出类型。
并确认它符合我们的预期:
scala> composable[(Int => String) :: (String => Char) :: HNil]
scala> composable[(Int => Long) :: (Long => Char) :: (Char => String) :: HNil]
scala> composable[(Int => String) :: (Symbol => Char) :: HNil]
<console>:23: error: could not find implicit value for evidence parameter...
前两个工作正常,而第三个无法编译。
是否可以定义每对连续元素都满足某种关系(约束)的列表类型。例如,一个函数列表,这样的函数可以组成:
val f1: A => B = ???
val f2: B => C = ???
val f3: C => D = ???
type SafeList = ??? // how to define this?
val fs: SafeList = f1 :: f2 :: f3 :: HNil // OK
val fs: SafeList = f1 :: f3 :: HNil // ERROR
通常不可能使用类型别名来描述像这样有趣的约束——相反,您需要一个类型 class 来作为类型具有某些 属性.[=14= 的证据]
使用 Shapeless 通常可以使用库提供的类型 classes 来完成此操作,但我认为这里不是这种情况。幸运的是,自己编写并不太难:
import shapeless._
// Evidence that an hlist is made up of functions that can be composed.
trait Composable[L <: HList] {
type In
}
object Composable {
type Aux[L <: HList, In0] = Composable[L] { type In = In0 }
implicit def composable0[A, B]: Aux[(A => B) :: HNil, A] =
new Composable[(A => B) :: HNil] {
type In = A
}
implicit def composable1[A, B, T <: HList]
(implicit tc: Aux[T, B]): Aux[(A => B) :: T, A] =
new Composable[(A => B) :: T] {
type In = A
}
}
def composable[L <: HList: Composable] {}
我们在这里所做的是描述如何以单身人士 HList
作为基本案例,归纳地建立证据。在每一步,我们都使用 In
type 成员来跟踪下一个(即列表中较早的)函数的输出类型。
并确认它符合我们的预期:
scala> composable[(Int => String) :: (String => Char) :: HNil]
scala> composable[(Int => Long) :: (Long => Char) :: (Char => String) :: HNil]
scala> composable[(Int => String) :: (Symbol => Char) :: HNil]
<console>:23: error: could not find implicit value for evidence parameter...
前两个工作正常,而第三个无法编译。