加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 无形:IsHCons,隐含未找到

发布时间:2020-12-16 18:43:05 所属栏目:安全 来源:网络整理
导读:我试图让这个相当愚蠢的例子工作,计划然后将它扩展到更有意义的东西. 但到目前为止没有运气:我找不到参数ihc的隐含值 我错过了什么? sealed trait Field[T] { def name: String }case class IntegerField(name: String) extends Field[Int]val year = Inte
我试图让这个相当愚蠢的例子工作,计划然后将它扩展到更有意义的东西.

但到目前为止没有运气:我找不到参数ihc的隐含值

我错过了什么?

sealed trait Field[T] { def name: String }
case class IntegerField(name: String) extends Field[Int]
val year = IntegerField("year")

val test = (year :: 23 :: HNil) :: (year :: 2 :: HNil) :: HNil

type TypedMap = IntegerField ::  Int  :: HNil

def get[L <: HList : <<:[TypedMap]#λ]
      (key: IntegerField,list: L)
      (implicit ihc: IsHCons.Aux[L,TypedMap,L]
    ): Option[Int] = {

  if( list == HNil ) return None
  val elem: TypedMap = list.head
  if( elem.head == key ) Some(elem.tail.head)
  else get(key,list.tail)

}

get(year,test)

解决方法

当你写IsHCons.Aux [L,L]时,你要求证明hlist L有头部TypedMap和尾部L,这意味着它是一个无限的hlist,这是不可能的,因为Scala没有允许这种任意递归类型(尝试写类似Foo = Int :: Foo的东西,例如 – 你会得到一个“非法循环引用”错误).它也可能不是你想要的.

一般来说,你不太可能在Shapeless中使用IsHCons,因为在类型中指示你想要的结构几乎总是更好.例如,以下两个定义执行相同的操作:

import shapeless._,ops.hlist.IsHCons

def foo[L <: HList](l: L)(implicit ev: IsHCons[L]) = ev.head(l)

和:

def foo[H,T <: HList](l: H :: T) = l.head

但第二个显然是可取的(它更清楚,它不需要在编译时找到额外的类型类实例,等等),并且几乎总是可以编写你想要这样做的任何东西.

另请注意,要求IsHCons实例意味着此处的递归将无法按照所述方式工作 – 您无法调用获取HNil,因为编译器无法证明它是HCons(因为它不是).

你确定你需要一个hlist吗?如果您要求hlist的所有成员都是TypedMap类型,那么您也可以使用Shapeless的Sized(如果您希望类型捕获长度)或甚至只是一个普通的旧List.

如果你真的想在这里使用HList,我建议你写一个新的类:

trait FindField[L <: HList] {
  def find(key: IntegerField,l: L): Option[Int]
}

object FindField {
  implicit val findFieldHNil: FindField[HNil] = new FindField[HNil] {
    def find(key: IntegerField,l: HNil) = None
  }

  implicit def findFieldHCons[H <: TypedMap,T <: HList](implicit
    fft: FindField[T]
  ): FindField[H :: T] = new FindField[H :: T] {
    def find(key: IntegerField,l: H :: T) = if (l.head.head == key)
      Some(l.head.tail.head)
    else fft.find(key,l.tail)
  }
}

def get[L <: HList](key: IntegerField,l: L)(implicit
  ffl: FindField[L]
): Option[Int] = ffl.find(key,l)

然后:

scala> get(IntegerField("year"),test)
res3: Option[Int] = Some(23)

scala> get(IntegerField("foo"),test)
res4: Option[Int] = None

这在Shapeless中是一种非常常见的模式 – 您可以归纳地描述如何在空的hlist上执行操作,然后在hlist上将头部预先添加到尾部,知道如何执行操作等.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读