18

Shapeless を学習しようとしています (バージョン 2.10.2 を使用)。非常に単純な拡張可能なレコードを作成しました。

val rec1 = ("foo" ->> 42) :: HNil

REPL によると、これには型があります

shapeless.::[Int with shapeless.record.KeyTag[String("foo"),Int],shapeless.HNil]

私は単純な関数を定義しようとしています:

def fun(x: ::[Int with KeyTag[String("foo"), Int], HNil]) = x("foo")

しかし、それはコンパイルさえしません。型宣言で String("foo") を使用できず、エラーが発生します。

2 つの質問があります。

  1. コードで拡張可能レコードのタイプを指定するにはどうすればよいですか?
  2. より多くのフィールドを持つレコードを操作する場合、型宣言の長さと複雑さが管理できなくなります。レコードの特定のインスタンスまたはその他の回避策を指定して、型のエイリアスを作成する方法はありますか?

編集

私はそれを発見しました:

val rec1 = ("foo" ->> 42) :: HNil
val rec2 = ("foo" ->> 43) :: HNil
var x = rec1
x = rec2

うまくいきます。rec1、rec2、および x は同じ型であると結論付けています。その型をコードで表現する方法がわかりません!

4

2 に答える 2

27

これは、あなたの質問に答えるかもしれないと思うもう少し一般的なものです。キーを持つ任意のレコードで機能するメソッドを書きたいとし"foo"ます。目撃者とセレクターの組み合わせを使用できます。

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

val w = Witness("foo")

def fun[L <: HList](xs: L)(implicit sel: ops.record.Selector[L, w.T]) = xs("foo")

その後:

scala> fun(("foo" ->> 42) :: HNil)
res0: Int = 42

または:

scala> fun(("bar" ->> 'a) :: ("foo" ->> 42) :: HNil)
res1: Int = 42

他のフィールドを持たないレコードのみを許可したい場合は、次のように記述できます。

def fun(l: Int with KeyTag[w.T, Int] :: HNil) = l("foo")

しかし、それはレコードの一般的な使用方法とはやや矛盾しています。

Scala 2.10 はシングルトン型を直接参照する方法を提供していないため、witness を正確に定義する必要があります。たとえば、議論については、Alois Cochard のShonaプロジェクトの私のフォークを参照してください。

最後の免責事項として、私は Shapeless 2.0 に慣れてきたばかりですが、Miles でさえ、この制限を回避するほど魔法のように機能するとは思いません。

于 2013-10-11T10:55:36.107 に答える