【发布时间】:2013-12-17 04:12:43
【问题描述】:
考虑到这个问题:Passing a Shapeless Extensible Record to a Function,Travis 的回答表明,每个将可扩展记录作为参数的函数都必须有一个隐式选择器作为参数。我想知道如果我们有很多此类函数,是否可以分解这些声明。 例如。 :
val w1 = Witness("foo1")
val w2 = Witness("foo2")
val w3 = Witness("foo3")
//Here some "magical" declarations avoiding to declara selectors in fun1, fun2, fun3 below
def fun1[L <: HList](xs: L) = ... //Access to foo1, foo2, foo3
def fun2[L <: HList](xs: L) = ... //Access to foo1, foo2, foo3
def fun3[L <: HList](xs: L) = ... //Access to foo1, foo2, foo3
谢谢
伯努瓦
12 月 10 日编辑
在尝试答案的代码时,会出现两个问题:
- 没有任何关于与 foo1、foo2、foo3 关联的数据的真实类型的信息:因此,像 fun1 这样的函数不能使用与这些类型关联的任何方法。例如,即使 foo3 是 Double,它也不能取平方根。
-
如果我用 ("foo1"->> "hello") :: ("foo2" -> 1)::("foo3" ->> 1.2)::HNiL 调用 fun1,结果是 (hello, 1, 1.2) 带类型 (selectors.s1.Out, selectors.s2.Out, selectors.s3.Out) 如果我尝试将 1 添加到最后一个值 (1.2),Scala 会抱怨它无法添加 Int 和 selectors.s3.Out ;但是如果我写:
val x = fun1(("foo1"->> "hello") :: ("foo2" -> 1)::("foo3" ->> 1.2)::HNil)我会写:
x._3 == 1.2scala 的答案是真的!
我曾尝试以这种方式修改代码,希望可以传播类型,但这并不能解决问题。我什至不能用 (foo1->> "hello") :: (foo2 -> 1)::(foo3 ->> 1.2)::HNil 作为参数调用 fun1:
object foo1 extends FieldOf[String]
object foo2 extends FieldOf[Int]
object foo3 extends FieldOf[Double]
val w1 = Witness(foo1)
val w2 = Witness(foo2)
val w3 = Witness(foo3)
case class HasMyFields[L <: HList](implicit
s1: Selector[L, w1.T],
s2: Selector[L, w2.T],
s3: Selector[L, w3.T]
)
object HasMyFields {
implicit def make[L <: HList](implicit
s1: Selector[L, w1.T],
s2: Selector[L, w2.T],
s3: Selector[L, w3.T]
) = HasMyFields[L]
}
def fun1[L <: HList](xs: L)(implicit selectors: HasMyFields[L]) = {
import selectors._
(xs(foo1), xs(foo2), xs(foo3))
}
有没有办法进步?
伯努瓦
【问题讨论】: