2016-08-10 9 views
4

これは、スカラ型レベルプログラミングに使用された開発者にとっては古典的な質問ですが、解決策を見つけることができませんでした(または検索する方法がわかりません)またはこれのためのパターン。私はこのクラスのユーザーはHList型パラメータ(Args)とそれをインスタンス化したいとクラスがそれぞれ指定された型のインスタンスを含むHListインスタンスを取得する方法を提供する結果の型を指定せずにシェイプレスマッパーを使用

abstract class TypedTest[Args <: HList](implicit val optMapper: Mapped[Args, Option]) { 
    type OptArgs = optMapper.Out 

    def options: OptArgs // to be implemented by subclasses 
} 

:私はこのようなクラスがあるとしOptionOptArgs)の内部にあります。私はこのために形のないMappedタイプのクラスを使用しています。私がのインスタンスがArgsでないとインスタンス化時に提供されないことに注意してください。

具体的なタイプをOptArgsと推測せず、def options = HNilなどの明らかに正しい実装であっても、コンパイルエラーが発生するため、このコードは機能しません。補助パターンを使用して、同じコード:

abstract class TypedTest[Args <: HList, OptArgs <: HList](implicit val optMapper: Mapped.Aux[Args, Option, OptArgs]) { 
    def options: OptArgs 
} 

これは、外部APIが不必要に冗長になりれ、インスタンス化時に両方のリストを指定するために私を強制します。このための回避策はありますか?

答えて

0

これは私の理解ではありますが、私は100%確実ではなく、訂正して喜んでいます。

タイプメンバーTypedTest.OptArgsは、抽象タイプではなくタイプエイリアスです。 TypedTestのすべてのサブクラスで同じタイプです。Mapped[Args, Option].Outのエイリアスは抽象タイプであり、すべてのサブクラス自体は統一できません。サブクラスが作成されると、型メンバーOptArgsはオーバーライドされません。

Out0ための実存タイプでMapped.Auxを使用する場合には、IIUC多かれ少なかれ同等以上にある、より明確になる:

abstract class TypedTest[Args <: HList](
    implicit val optMapper: Mapped.Aux[Args, Option, T] forSome { type T }) { 

    type OptArgs = optMapper.Out 

    def options: OptArgs // to be implemented by subclasses 
} 

val intTest = new TypedTest[Int :: HNil] { 
    def options = Some(1) :: HNil 
} 

Error:(18, 29) type mismatch; 
found : shapeless.::[Some[Int],shapeless.HNil] 
required: this.OptArgs 
    (which expands to) T 
    def options = Some(1) :: HNil 

は、残念ながら、私はOutを追加することを除いて、すべての可能な解決策を認識していませんよ抽象型としてOptArgsを定義し、各サブクラスで明示的に指定します。

+0

'OptArgs'は抽象型ではなく、' optMapper'の値に依存するパス依存型です。 'OptArgs'をタイプエイリアスとして定義しましたが、その定義を省略して' def options:optMapper.Out'と書くだけでした。パス依存型は、たとえ抽象型として定義されていても意味を持って使用できます。つまり、 'Mapper.Aux'の定義はパス依存型を型パラメータに"変換 "します。しかし、この場合には解決策がない可能性があります。 –

関連する問題