3

私は HList / KList を発見しました。それらはかなりクールです。私は実際のユース ケースを持っています。このユース ケースでは、保存された型情報を持つ異種の型と可変長のコンテナーが非常に役立ちます (詳細については、以下の背景を参照してください)。ただし、H/KList をメソッド パラメーターとして使用する方法を理解していません。この場合、パラメーターに完全に型注釈を付けたり、型情報を緩めたりする必要があります。もちろん、完全な型が不明な場合、H/KLists をパラメーターとして使用することはできますか? 型情報を失うことなく H/KList を参照する方法は?

「型リスト」を使用して、異種の可変長型パラメーターのタプルを参照できますか? ここでは、次のように述べ ... the types of the elements can be tracked separate from the actual element values. To do this we create an purely abstract type (it has no instances) which models a list of types, let's call it TList. ています。いじってみましたが、パラメーターとして HList の型注釈に使用する方法をまだ理解していません。

基本的に、私はこのようなものが欲しいです:

implicit def hlistToTypedLink[TL](a: HList[TL]):TypedLink[TL] = new TypedLink[TL](a.map(a:X => new TypedHandle[X]))

ここで、TL は型リストを指し、X は現在の要素の型を指します。したがって、ここで HList は、型リスト TL によってパラメータ化された別のタプルのようなコンテナーである TypedLink にマップする必要があります。要素は、現在の型 X で型指定された、さらに別のパラメーター化されたコンテナー TypedHandle にそれぞれラップされます。

これは可能ですか?

Shapeless の HList とその "unify" メソッドを見ましたが、問題は同じままです。可変長以外に、パラメーター リストでそれを参照する方法がわかりません。

2 番目の希望は、KList を使用することでした。TypedHandle は同じコンストラクターを持つ共通のコンテナーであるため、私の場合に適用されます。apocalisp によると、 KListを使用すると、注釈を入力するのが簡単に見えます。

 val m = List(1, 2, 3, 4) :^: List("str1", "str2") :^: KNil

タイプは次のとおりです。

 KCons[Int,java.lang.String :: HNil,List]

ただし、問題は同じままです。メソッド定義では、それが

KCons[String, Int :: HNil, TH]

または

KCons[Foo, Bar, Baz :: HNil, TH]

そのため、KList をメソッド パラメータとして型注釈する方法もわかりません。

ヒントをありがとう!

背景: 私は優れた OO およびグラフ データベース hypergraphdb の便利な scala 拡張機能を作成しています。Hypergraphdb のハイパーエッジである HGLink は、基本的に HGHandle のタプルです。HGHandle は、それ自体が型付けされたアトムを参照します。したがって、HGLink 自体は異種の型であり、可変長です。ただし、HGLink の実装はこれまで型指定されておらず、型指定されていない HGHandle の実装によって構築されていました。Java の型システムは、hypergraphdb の (はるかに優れた) 型システム (たとえば、より高い種類の型もある) を反映するほど表現力がないと思います。

基本的に、私は scala の型システムと hypergraphdb の型システムを橋渡ししようとしています。多くのことを学んでいますが、今までは本当に楽しかったです。TypedHandle は、他の多くのハックに加えて、すでにうまく機能しています。

アドバイスをありがとう。

4

2 に答える 2

8

あなたが何を求めているのかは私には完全には明らかではありませんが、形状のない関数と多形関数hlistToTypedLinkの値を使用して処理できるように見えます。HList

scala> import shapeless._ ; import TypeOperators._
import shapeless._
import TypeOperators._

scala> class TypedHandle[T]
defined class TypedHandle

scala> class TypedLink[L <: HList](l : L)
defined class TypedLink

scala> object MkTypedHandle extends (Id ~> TypedHandle) {
     |   def apply[T](t : T) = new TypedHandle[T]
     | }
defined module MkTypedHandle

scala> def hlistToTypedLink[L <: HList, M <: HList](a: L)
     |   (implicit mapper: MapperAux[MkTypedHandle.type, L, M]) =
     |     new TypedLink[M](a map MkTypedHandle)
hlistToTypedLink: [L <: HList, M <: HList](a: L)
  (implicit mapper: MapperAux[MkTypedHandle.type,L,M])TypedLink[M]

scala> hlistToTypedLink(23 :: "foo" :: true :: HNil)
res0: TypedLink[TypedHandle[Int] :: TypedHandle[String] ::
  TypedHandle[Boolean] :: HNil] = TypedLink@51fb5716

HList a基本的に、各要素を aTypedHandleでラップし、結果HListを a でラップして、引数をマップしたいようですTypedLink。すべての場合において、ラッパーはそのコンテンツのタイプで正確にパラメータ化されます。

上記のように、これは shapeless を使用して可能HList mapです。ここには 2 つの重要な要素があります。まず、ラップされた要素を作成する際にMkTypedHandleマップできるポリモーフィックな関数のような値の定義です。次に、マップ操作を駆動する暗黙の証人です。HList aHListTypedLinkmapper

于 2012-09-03T19:46:27.857 に答える
2

私のブログ投稿を参照してください。TList は値ストレージのない単純な HList です。つまり、リストの型表現のみがあり、ランタイム表現はありません。利点の 1 つは、たとえば配列 (Metascala の HArray) など、さまざまな、おそらくより効率的な値ストレージのタイプを容易にすることです。TList は共用体型 (基本的には型セット) のモデル化にも使用できますが、Scala の型システムはこれを型レベルでのみ行うには十分強力ではありません (Haskell の型システムは私が思うに)。

于 2012-09-04T10:56:05.323 に答える