【问题标题】:Subtype polymorphism in shapeless mapping无形映射中的亚型多态性
【发布时间】:2014-01-03 00:43:51
【问题描述】:

我已经构建了以下内容:

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.::[列表[字符串],shapeless.HNil]]]"。我在这里期待的子类型多态性,即在 Iterable 上工作的函数应该在 List 上工作,由于某种原因失败了。这是为什么?有没有办法让我解决这个问题,或者我自己的贪婪会成为我的毁灭?

【问题讨论】:

    标签: scala shapeless


    【解决方案1】:

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

    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
    

    【讨论】:

    • 谢谢!我用的是第一个。此解决方案引发了有关启用更高种类类型的警告,该警告已通过导入 scala.language.higherKinds 消除。不过,我不确定我是否真的理解解决方案。我已经看到“at”到处都是无形的,但被它弄糊涂了。它有什么作用,你知道它是在哪里定义的吗?
    • @jcrudy:where at is defined and how it works 是一个很好的 SO 问题。答案太大了,无法评论。您应该将其作为 SO 问题提出(不要忘记提及 ~&gt;apply 方法)。你甚至可以从Miles Sabin得到答案。
    • @senia:如果类型 T 必须是有界的,那么第一个解决方案将如何工作,例如可迭代[T
    • @senia 嗯,原来我的问题与使用自定义类型作为 L[T] 的上限有关。在stackoverflow.com/questions/42853858/… 开始了一个新问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    相关资源
    最近更新 更多