【问题标题】:Find type class instances for Shapeless HList查找 Shapeless HList 的类型类实例
【发布时间】:2023-03-23 07:55:01
【问题描述】:

假设我有一个 trait Show[T],比如 Scalaz 中的那个:https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/Show.scala#L9

我还有一个 Shapeless HList,可能看起来像 "1" :: 2 :: 3L :: HNil

有没有办法找到每个元素的 Show 实例并应用 shows 以便我最终得到 "1" :: "2" :: "3L" :: HNil

如果任何元素的类型在范围内没有隐式 Show 实例,我会想要一个编译错误。

我认为,如果我构建了 Show 实例中的 HList,我应该能够使用 zipApply 来获得我想要的 HList,但我不知道是否有办法让 Scala 推断 Show 实例中的 HList,而不是我手动构建它。

【问题讨论】:

    标签: scala shapeless hlist


    【解决方案1】:

    如果您的目标是应用 Show 实例,并且您不关心构建其中的 HList,那么最简单的方法可能是使用多态函数:

    import scalaz._, Scalaz._, shapeless._
    
    val xs = "1" :: 2 :: 3L :: HNil
    
    object show extends Poly1 {
      implicit def forShowable[A: Show] = at[A](_.shows)
    }
    
    val strings: String :: String :: String :: HNil = xs map show
    

    您可以通过稍微更改Poly1 来获得实例的HList

    object showInstance extends Poly1 {
      implicit def forShowable[A: Show] = at[A](_ => Show[A])
    }
    

    在某些情况下,定义您自己的类型类以收集您拥有某些类型类实例的证据会很有用:

    trait AllShowable[L <: HList, S <: HList] {
      def instances: S
    }
    
    implicit object hnilAllShowable extends AllShowable[HNil, HNil] {
      def instances = HNil
    }
    
    implicit def hlistAllShowable[H: Show, TL <: HList, TS <: HList](
      implicit ts: AllShowable[TL, TS]
    ) = new AllShowable[H :: TL, Show[H] :: TS] {
      def instances = Show[H] :: ts.instances
    }
    

    但通常使用需要实例的多态函数进行映射就可以正常工作。

    【讨论】:

    • Travis,你怎么回答得这么快?当我发布这篇文章时,我有一种感觉,要么答案是“这是不可能的”,要么解决方案非常简单,以至于我最终会感到愚蠢。很高兴看到是后者:)
    • 周六早上我正在做一个没完没了的项目,所以能够回答这样的问题是一个非常受欢迎的士气鼓舞。而且我不确定任何关于 Shapeless 的精心设计的问题都可以被认为是“愚蠢的”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多