2017-06-09 3 views
2

特定のタイプのフィールドを選択できるタイプクラスを作成しようとしています。これは私がこれまでにやっていることですが、コンパイラがSelector.Auxタイプ別にフィールドを選択

case class AddressKey(street: String, city: String) 

trait AddressKeySelector[A] { 
    def addressKey(v: A): AddressKey 
    def addressKeyColumnName: String 
} 

object AddressKeySelector { 

    implicit def typeAddressKeySelector[A, Repr <: HList, K](
     implicit gen: Generic.Aux[A, Repr], 
     reprSelector: Selector.Aux[Repr, K, AddressKey]): AddressKeySelector[A] = 
    new AddressKeySelector[A] { 
     override def addressKey(v: A): AddressKey = reprSelector(gen.to(v)) 

     override def addressKeyColumnName: String = ??? 
    } 
} 

を見つけることができない1つのみがある場合には、うまく動作するはずです。この

case class MyType(addressKeyField: AddressKey, otherField: String) 
val data = MyType(AddressKey("addr", "city"), "other") 
val addrKey = AddressKeySelector[MyType].addressKey(data) 
// addrKey: AddressKey = AddressKey(addr,city) 
val addrField = AddressKeySelector[MyType].addressKeyColumnName(data) 
// addrField: String = addressKeyField 

のように使用されますAddressKey型のフィールド。どのようにそれを実装する上の任意のアイデア?

答えて

2

ops.hlist.SelectorにはAuxが含まれていないので、私はそれを使用していると仮定しています。フィールド名を抽出するときに、LabelledGenericops.record.Selectorを代わりに使用することをお勧めします。しかし、Selectorは値でキーを検索している間は "key"(K)でしか検索できず、 "value"(AddressKey)で検索できないため、Selector.Aux[Repr, K, AddressKey]はまだ機能しません。

import shapeless._, ops.record._ 

trait AddressKeySelector[A] { 
    def addressKey(v: A): AddressKey 
    def addressKeyColumnName: String 
} 

object AddressKeySelector { 
    def apply[A](implicit sel: AddressKeySelector[A]): sel.type = sel 

    implicit def typeAddressKeySelector[A, Repr <: HList, K <: Symbol, Swapped <: HList](
     implicit 
     gen: LabelledGeneric.Aux[A, Repr], 
     swap: SwapRecord.Aux[Repr, Swapped], 
     swappedSelector: Selector.Aux[Swapped, AddressKey, K], 
     reprSelector: Selector.Aux[Repr, K, AddressKey] 
): AddressKeySelector[A] = 
    new AddressKeySelector[A] { 
     override def addressKey(v: A): AddressKey = reprSelector(gen.to(v)) 

     override def addressKeyColumnName: String = swappedSelector(swap()).name 
    } 
} 

しかし、動作しませんsome reasonのために:

理想的には私はあなたがこのようにそれを実装すると思います。

だから、私はあなたの最善の策は、あなた自身で価値のある検索を実装することだと思います。それは比較的簡単です。あなたはops.hlist.Selectorからインスピレーションを得ることができます。 HlistのすべてのエントリはLabelledGenericとして符号化され、labelled.FieldType[Key,Value]としてエンコードされ、実行時の値Key(つまりフィールド名)はWitness.Aux[Key]で取得できることに注意してください。

+0

SwapRecord型クラスは何をしていますか? – Mikel

+0

'HList'の' FieldType [K、V] 'を' FieldType [V、K] 'に入れ替えます。 –

+1

キーでのみ選択できます。したがって、キーと値を入れ替えると、値(キーになっている)を選択できます。 –

関連する問題