首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从光滑的HLIST中获取元素(或将光滑的HLIst转换为无形状的HList)

从光滑的HLIST中获取元素(或将光滑的HLIst转换为无形状的HList)
EN

Stack Overflow用户
提问于 2017-09-15 16:03:39
回答 1查看 483关注 0票数 3

我有自动生成的scala代码使用灵活的编码。我看到一些表行被实现为HLists。(但这些都是光滑的HList,而不是普通的无型HList)

现在,我需要一个来自HList的特定元素,它以行的形式返回给灵活的查询。

我在谷歌上找到了这条线

Getting elements from an HList

但这并不适用于光滑的HList。它适用于无形状的HList。

我也尝试了应用的方法。

val : Long = slickHList(2)

但这不能编译,因为类型Any不符合exected类型的Long。我不想做.asInstanceOf

是否有一种类型错误的方法可以访问光滑的HList元素?

编辑:基于下面的输入,我编写了下面的代码

代码语言:javascript
复制
package com.abhi

object SlickAndShapeless {
   import slick.collection.heterogeneous.{HCons, HList, HNil}
   import slick.collection.heterogeneous.syntax.HNil

   type MyRow = HCons[Long, HCons[String, HNil]]
   val row : MyRow = 1L :: "foo" :: HNil
   import HListExtensions._
   val hlist = row.asShapeless
   val container = new Container(hlist)
   val item = container.get(1)
}

class Container[L <: shapeless.HList](list: L) {
   import shapeless._
   import nat._
   import ops.hlist._
   def get(n: Nat)(implicit at: At[L, n.N]): at.Out = list[n.N]
}

object HListExtensions {
   import slick.collection.heterogeneous.{HNil => SHNil, HList => SHList, HCons}
   import shapeless.{::, HList, HNil}

   implicit class HListShapelessSlick(val list: HList) extends AnyVal {
      def asSlick : SHList = list match {
         case HNil => SHNil
         case head :: tail => head :: tail.asSlick
      }
   }

   implicit class HListSlickShapeless(val list: SHList) extends AnyVal {
      def asShapeless : HList = list match {
         case SHNil => HNil
         case HCons(head, tail) => head :: tail.asShapeless
      }
   }
}

上面的代码的问题是,从val item = container.get(1)获得的val item = container.get(1)类型是at.Out,而不是我所期望的Long

build.sbt

代码语言:javascript
复制
libraryDependencies ++= Seq(
   "com.typesafe.slick" % "slick_2.12" % "3.2.1",
   "com.chuusai" % "shapeless_2.12" % "2.3.2"
)

我还看到两个编译器错误。

代码语言:javascript
复制
Error:(19, 35) Implicit not found: shapeless.Ops.At[shapeless.HList, shapeless.Succ[shapeless._0]]. You requested to access an element at the position shapeless.Succ[shapeless._0], but the HList shapeless.HList is too short.
   val item : Long = container.get(1)
Error:(19, 35) not enough arguments for method get: (implicit at: shapeless.ops.hlist.At[shapeless.HList,shapeless.Succ[shapeless._0]])at.Out.
Unspecified value parameter at.
   val item : Long = container.get(1)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-15 17:16:05

可以创建扩展方法:

代码语言:javascript
复制
object HListExtensions {

  import slick.collection.heterogeneous.{HNil => SHNil, HList => SHList, HCons}
  import shapeless.{ ::, HList, HNil }

  implicit class HListShapelessSlick(val list:HList) extends AnyVal {
    def asSlick:SHList = list match {
      case HNil => SHNil
      case head :: tail => head :: tail.asSlick
    }
  }

  implicit class HListSlickShapeless(val list:SHList) extends AnyVal {
    def asShapeless:HList = list match {
      case SHNil => HNil
      case HCons(head, tail) => head :: tail.asShapeless
    }
  }
}

示例:

代码语言:javascript
复制
scala>import HListExtensions._
import HListExtensions._

scala> val x1:HList = 1 :: 2 ::  HNil
x1: slick.collection.heterogeneous.HList = 1 :: 2 :: HNil

scala> x1.asShapeless
res1: shapeless.HList = 1 :: 2 :: HNil

scala> x1.asShapeless.asSlick
res2: slick.collection.heterogeneous.HList = 1 :: 2 :: HNil

我希望这能帮到你。

编辑:这是类型级别的解决方案。

代码语言:javascript
复制
object HListsConvertersTypeLevel {

  import shapeless.{::}

  sealed trait HConv[From <: heterogeneous.HList, To <: shapeless.HList] {
    def convert(list: From): To
  }

  implicit def buildHConvNil: HConv[heterogeneous.HNil.type, shapeless.HNil] =
    new HConv[heterogeneous.HNil.type, shapeless.HNil] {
      override def convert(list: heterogeneous.HNil.type): shapeless.HNil = shapeless.HNil
    }

  implicit def buildHConv[H, T <: heterogeneous.HList, T2 <: shapeless.HList](
      implicit conv: HConv[T, T2]): HConv[HCons[H, T], ::[H, T2]] = new HConv[HCons[H, T], ::[H, T2]] {

    override def convert(list: HCons[H, T]): ::[H, T2] = {
      list.head :: conv.convert(list.tail)
    }
  }

  def toShapeless[A <: heterogeneous.HList, B <: shapeless.HList](list: A)(implicit conv: HConv[A, B]): B = conv.convert(list)

}

示例:

代码语言:javascript
复制
object SlickAndShapeless {
  import slick.collection.heterogeneous.{HCons, HNil}
  import slick.collection.heterogeneous.syntax.HNil

  type MyRow = HCons[Long, HCons[String, HNil]]
  val row: MyRow = 1L :: "foo" :: HNil

  import HListsConvertersTypeLevel._
  val hlist         = toShapeless(row)
  val item: Long    = hlist.head
  val item2: String = hlist.tail.head
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46243627

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档