2016-07-04 11 views
2

'Identifiable'のサブタイプであるいくつかのタイプに対して、汎用の特性 'Repo'を作成しようとしています。私の計画は、 'Identifiable'サブタイプを記述するジェネリックTypeTag [HList]を渡すことによって、 'R​​epo'の実装者をインスタンス化することです。コンパイル時にHListタイプの上限を適用する

HListで渡される型が 'Identifiable'のサブタイプであることをコンパイラに保証させるにはどうすればよいですか?ここで

は、私がこれまで持っているものです: Type inference on contents of shapeless HList 違いは、私が仕事にHListの実装を持っていないです。

//All types in HList must extend Identifiable, how to enforce that at compile time? 
    trait Repo { 
     implicit val ltag: TypeTag[L] forSome {type L <: HList} 
     .. 
    } 

    trait Identifiable { 
     .. 
    } 

    case class Person(..) extends Identifiable 
    case class Address(..) 

    //This should compile 
    class MyRepo 
     (implicit val ltag: TypeTag[Person :: HNil]) 
     extends Repo { 
     .. 
    } 

    //This should not 
    class MyRepo 
     (implicit val ltag: TypeTag[Address :: HNil]) 
     extends Repo { 
     .. 
    } 
//HList can contain an unknown number of types 

私が関係しているように見えるこの質問を見てきましたどのようにして上限の計算をどのように行うことができるのかは分かりません。

答えて

3

HListには、https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/hlistconstraints.scalaによって提供される一連の制約があります。

あなたの後にいるのはおそらくLUBConstraintです。 Lのすべての要素がBのサブタイプである

Typeクラスの目撃:文書を引用。

使用するには、LUBContraint[L, Identifiable]という暗黙的な証拠を要求するだけです。

など。

trait Repo[L <: HList] { 
    implicit val ltag: TypeTag[L] 
    implicit val ev: LUBConstraint[L, Identifiable] 
} 

trait Identifiable 
case class Person(name: String) extends Identifiable 
case class Address(street: String) 

type P = Person :: HNil 
class MyPersonRepo(implicit 
    val ltag: TypeTag[P], 
    val ev: LUBConstraint[P, Identifiable] 
) extends Repo[P] 


type A = Address :: HNil 
class MyAddressRepo(implicit 
    val ltag: TypeTag[A], 
    val ev: LUBConstraint[A, Identifiable] 
) extends Repo[A] 

new MyPersonRepo // this works 
new MyAddressRepo // this doesn't 

かわり形質の抽象クラスを使用して喜んでいる場合は、クラスを拡張するとき今、あなたはすぐにエラーが発生します

abstract class Repo[L <: HList](implicit 
    val ltag: TypeTag[L], 
    val ev: LUBConstraint[L, Identifiable] 
) 

trait Identifiable 
case class Person(name: String) extends Identifiable 
case class Address(street: String) 

type P = Person :: HNil 
class MyPersonRepo extends Repo[P] 

type A = Address :: HNil 
class MyAddressRepo extends Repo[A] 

すべてがよりよいすることができます。

+0

この証拠を実装者からの形質に渡すための構文は何でしょうか?型パラメータを型に渡すことができないので、私の頭を包むのが難しいです。 – eirirlar

+0

@eirirlar上の例を参照 –

+0

大変ありがとう – eirirlar

関連する問題