首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >,将KList的类型参数作为HList获取

,将KList的类型参数作为HList获取
EN

Stack Overflow用户
提问于 2014-12-29 13:55:02
回答 2查看 550关注 0票数 10

假设我有一个双参数的KList,为了便于论证,它有类型构造函数Option_,即;

代码语言:javascript
复制
type Example = Option[Int] :: Option[String] :: HNil

有办法检索由类型参数组成的Hlist吗?

代码语言:javascript
复制
type Params = Int :: String :: HNil

例如,我可能可以定义某种任意的getOrElse方法

代码语言:javascript
复制
getOrElse(ex:Example, default:Params):Params

现在,我正在寻找类似于这种形式的东西(或者类似于我提议的类型结构可能不可行)。

代码语言:javascript
复制
case class MyOptionList[L <: HList](maybes:L) {
  type Concrete = {somehow the hlist params types as an Hlist}
  def getOrElse(default:Concrete):Concrete = ???

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-29 19:09:34

我不是迈尔斯,但是你想用无形的Comapped来完成你想做的事情是有可能的

代码语言:javascript
复制
import shapeless._, ops.hlist.Comapped

case class MyOptionList[L <: HList, C <: HList](maybes: L)(
  implicit val comapped: Comapped.Aux[L, Option, C]
) {
  def getOrElse(default: C): C = default // Not a useful implementation
}

然后:

代码语言:javascript
复制
scala> val x: Int :: HNil = MyOptionList(Option(1) :: HNil).getOrElse(2 :: HNil)
x: shapeless.::[Int,shapeless.HNil] = 2 :: HNil

注意,在某些情况下,可以更方便地将约束放在方法上:

代码语言:javascript
复制
case class MyOptionList[L <: HList](maybes: L) {
  def getOrElse[C <: HList: ({ type l[x] = Comapped.Aux[L, Option, x] })#l](
    default: C
  ): C = default
}

这里的用法是相同的,但是在case类上没有额外的类型参数。如果要使用此方法,但限制创建MyOptionList以不允许非Option成员,则可以在其类型参数列表中使用L <: HList: *->*[Option]#λ

票数 8
EN

Stack Overflow用户

发布于 2014-12-29 15:02:10

@MilesSabin可能会给出一个更优雅的答案,但是您可以用手工递归地构造它,就像许多未成形的内部事物的书写方式:

代码语言:javascript
复制
sealed trait GetOrElse[L <: HList] {
  type Concrete <: HList
  def getOrElse(ex: L, default: Concrete): Concrete
}
object GetOrElse {
  implicit def nil = new GetOrElse[HNil]{
    type Concrete = HNil
    def getOrElse(ex: HNil, default: HNil) = HNil
  }
  implicit def cons[H, T <: HList](implicit tl: GetOrElse[T]) =
    new GetOrElse[Option[H] :: T]{
      type Concrete = H :: tl.Concrete
      def getOrElse(ex: Option[H] :: T, default: Concrete) =
        ex.head.getOrElse(default.head) ::
          tl.getOrElse(ex.tail, default.tail)
    }
  def apply[L <: HList](implicit goe: GetOrElse[L])
    : GetOrElse[L]{type Concrete = goe.Concrete} = goe
}

case class MyOptionList[L <: HList, C](maybes:L)(
  implicit goe: GetOrElse[L]{type Concrete = C}) {
  def getOrElse(default:C):C = goe.getOrElse(maybes, default)
}

(可能使用类型成员而不是类型参数是可能的,但我对这些类型信息何时被吃掉感到困惑,因此我倾向于在任何地方都使用类型参数)

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27690254

复制
相关文章

相似问题

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