无法过滤任意HLists

时间:2015-12-07 16:06:17

标签: scala shapeless

所以我试图在类型可以变化的HList上过滤类型:

import shapeless._
import ops.hlist._, ops.traversable._
object FlexibleTypes {

  sealed trait Data {
    type H <: HList
    def data: H

    def ints[Prefix <: HList, Suffix <: HList](
      implicit
      partitionIntent:           Partition.Aux[H, Int, Prefix, Suffix],
      prefixToTraversableIntent: ToTraversable.Aux[Prefix, List, Int]
    ): List[Int] = data.filter[Int].to[List]

    def strings[Prefix <: HList, Suffix <: HList](
      implicit
      partitionIntent:           Partition.Aux[H, String, Prefix, Suffix],
      prefixToTraversableIntent: ToTraversable.Aux[Prefix, List, String]
    ): List[String] = data.filter[String].to[List]
  }

  def Data1[D <: Int :: String :: HNil]( _data: D ) = new Data {
    type H = D
    val data = _data
  }
  def Data2[D <: Int :: HNil]( _data: D ) = new Data {
    type H = D
    val data = _data
  }

  val datas1 = List(
    Data1( 1 :: "a" :: HNil ),
    Data1( 2 :: "b" :: HNil )
  )

  val datas2 = List(
    Data1( 1 :: "a" :: HNil ),
    Data1( 2 :: "b" :: HNil ),
    Data2( 3 :: HNil )
  )

  val ints1 = datas1.flatMap( _.ints ) // compiles
  val ints2 = datas2.flatMap( _.ints ) // does not compile

}

我为ints2获得的编译错误是:

[error] /Users/caente1/xdotai/xdotai-scala/idris/src/main/scala/flexible.scala:43: could not find implicit value for parameter partitionIntent: shapeless.ops.hlist.Partition.Aux[x$11.H,Int,Prefix,Suffix]
[error]   val ints2 = datas2.flatMap( _.ints ) // does not compile
[error]                                 ^
[error] one error found
[error] (idris/compile:compileIncremental) Compilation failed

如果H是类型参数,也会发生同样的情况。

1 个答案:

答案 0 :(得分:2)

所以它似乎必须HList一直向下:

import shapeless._
import ops.hlist._, ops.traversable._
object FlexibleTypes {

  case class Data[H <: HList]( data: H )
  def Data1[D <: Int :: String :: HNil]( _data: D ) = Data( _data )
  def Data2[D <: Int :: HNil]( _data: D ) = Data( _data )

  object ints extends Poly1 {
    implicit def toInts[H <: HList, Prefix <: HList, Suffix <: HList](
      implicit
      partition:           Partition.Aux[H, Int, Prefix, Suffix],
      prefixToTraversable: ToTraversable.Aux[Prefix, List, Int]
    ) = at[Data[H]]( _.data.filter[Int].to[List] )
  }

  val datas =
    Data1( 1 :: "a" :: HNil ) ::
      Data1( 2 :: "b" :: HNil ) ::
      Data2( 3 :: HNil ) ::
      HNil

  val is: List[Int] = datas.map( ints ).toList.flatten

}