この質問 : 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日編集
答えのコードを試すと、次の 2 つの問題が発生します。
- foo1、foo2、foo3 に関連付けられたデータの実際の型については何も通知されません。したがって、 fun1 のような関数は、これらの型に関連付けられたメソッドを使用できません。たとえば、foo3 が Double であっても、その平方根を取ることはできません。
fun1 を ("foo1"->> "hello") :: ("foo2" -> 1)::("foo3" ->> 1.2)::HNiL で呼び出すと、結果は (hello, 1, 1.2 ) with type (selectors.s1.Out, selectors.s2.Out, selectors.s3.Out) 最後の値 (1.2) に 1 を追加しようとすると、Scala は Int とセレクターを追加できないと文句を言います。 s3.Out ;しかし、私が書いた場合:
val x = fun1(("foo1"->> "hello") :: ("foo2" -> 1)::("foo3" ->> 1.2)::HNil)
私は書くことができます:
x._3 == 1.2
scala は True と答えます。
この方法でコードを変更しようとしましたが、型が伝播されることを回避しましたが、問題は解決しません。(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))
}
上達する方法はありますか?
ブノワ