Passing a Shapeless Extensible Record to a Function (continued)

╄→尐↘猪︶ㄣ 提交于 2019-11-28 08:42:47

You can define your own type class to gather the evidence that the record has the fields you need:

import shapeless._, ops.record.Selector, record._, syntax.singleton._

val w1 = Witness("foo1")
val w2 = Witness("foo2")
val w3 = Witness("foo3")

case class HasMyFields[L <: HList](implicit
  s1: Selector[L, w1.T, String],
  s2: Selector[L, w2.T, Int],
  s3: Selector[L, w3.T, Double]
)

object HasMyFields {
  implicit def make[L <: HList](implicit
    s1: Selector[L, w1.T, String],
    s2: Selector[L, w2.T, Int],
    s3: Selector[L, w3.T, Double]
  ) = HasMyFields[L]
}

And then, for example:

def fun1[L <: HList](xs: L)(implicit selectors: HasMyFields[L]) = {
  import selectors._

  (xs("foo1"), xs("foo2"), xs("foo3"))
}

It's still a little verbose, especially since the import is necessary, but much less so than requiring all of the selectors individually as implicit parameters.

The out type of a given field can be specified using:

Selector[L, w1.T] { type Out = String }

Also, we can slightly simplify the syntax using a type constructor:

import shapeless._, ops.record.Selector, record._, syntax.singleton._

val w1 = Witness("foo1")
val w2 = Witness("foo2")
val w3 = Witness("foo3")

type HasFoo1[L <: HList] = Selector[L, w1.T] { type Out = String }
type HasFoo2[L <: HList] = Selector[L, w2.T]
type HasFoo3[L <: HList] = Selector[L, w3.T]

@implicitNotFound("${L} should have foo1, foo2 and foo3")
case class HasMyFields[L <: HList](implicit s1: HasFoo1[L], s2: HasFoo2[L], s3: HasFoo3[L])

object HasMyFields {
  implicit def make[L <: HList : HasFoo1 : HasFoo2 : HasFoo3] = HasMyFields[L]
}


def fun1[L <: HList : HasMyFields](xs: L) = {
  val selectors = implicitly[HasMyFields[L]]
  import selectors._
  (xs("foo1").length, xs("foo2"), xs("foo3"))
}

fun1(("foo1"->> "hello") :: ("foo2" ->> 1)::("foo3" ->> 1.2)::HNil)

// Does not compile: the value in foo1 is not a String
fun1(("foo1"->> 2)       :: ("foo2" ->> 1)::("foo3" ->> 1.2)::HNil)
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!