5

我已经构建了以下内容:

import shapeless._
import poly._

object Main {
    def main(args: Array[String]) = {

        object iterateOverHList extends (List ~> Iterator) {
            def apply[T](it: List[T]) = it.iterator
        }

        val x = List(1,2,3) :: List("cat","dog") :: HNil

        val xIt = x map iterateOverHList

    }
}

上面的代码效果很好,很棒。不过,我还想要更多。我想,而不是指定我的 HList 将包含列表,允许任何 Iterable。像这样:

import shapeless._
import poly._

object Main {
    def main(args: Array[String]) = {

        object iterateOverHList extends (Iterable ~> Iterator) {
            def apply[T](it: Iterable[T]) = it.iterator
        }

        val x = List(1,2,3) :: List("cat","dog") :: HNil

        val xIt = x map iterateOverHList

    }
}

第二个版本无法编译,并显示消息“找不到参数映射器的隐式值:shapeless.ops.hlist.Mapper[iterateOverHList.type,shapeless.::[List[Int],shapeless.::[List[String] ],shapeless.HNil]]]"。我在这里期望的子类型多态性,即在 Iterable 上工作的函数应该在 List 上工作,由于某种原因失败了。这是为什么?有没有办法让我解决这个问题,或者我自己的贪婪会成为我的毁灭吗?

4

1 回答 1

8

~>适用于确切类型。如果你想要一个你的Poly1任何子类型,Iterable你应该像这样创建它:

object iterateOverHList extends Poly1 {
  implicit def iterable[T, L[T] <: Iterable[T]] = at[L[T]](_.iterator)
}

您还可以创建一个Poly1适用于某些类型的,可以Iterable像这样对待的:

import scala.collection.generic.IsTraversableOnce
object iterateOverHList extends Poly1 {
  implicit def iterable[L](implicit i: IsTraversableOnce[L]) =
    at[L](i.conversion(_).toIterator)
}

val x = "abc" :: List(1,2,3) :: HNil
val xIt = x map iterateOverHList
// xIt: shapeless.::[Iterator[Char],shapeless.::[Iterator[Int],shapeless.HNil]] = non-empty iterator :: non-empty iterator :: HNil
于 2014-01-03T01:02:38.190 回答