9

この質問 : 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 つの問題が発生します。

  1. foo1、foo2、foo3 に関連付けられたデータの実際の型については何も通知されません。したがって、 fun1 のような関数は、これらの型に関連付けられたメソッドを使用できません。たとえば、foo3 が Double であっても、その平方根を取ることはできません。
  2. 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))
 }

上達する方法はありますか?

ブノワ

4

2 に答える 2