2016-11-01 5 views
3

に以下をコンパイルしていないので、最後の行でコンパイルされません:暗黙的に包まれた形質は

object ImplicitWrappedTraitWithType { 

    trait Wrapper[+T] { 
    def unwrap: T 
    } 

    object Wrapper { 
    def apply[T](implicit w: Wrapper[T]): Wrapper[T] = w 
    } 

    trait IO[In] { 
    type Out 

    def out: Out 
    } 

    implicit def decoder[In]: Wrapper[IO[In] {type Out = String}] = new Wrapper[IO[In] {type Out = String}] { 
    override def unwrap: IO[In] {type Out = String} = new IO[In] { 
     override type Out = String 
     override val out: Out = "yeah" 
    } 
    } 

    val wrap = Wrapper[IO[String]] 
    val io: IO[String] = wrap.unwrap 
    val out: String = io.out //actual type: unwrap.Out 
} 

私はval outStringあるコンパイラを説得するために何ができますか?


編集前 -例1この

を無視する - これはコンパイルされない:

object ImplicitWrappedTraitWithType { 
    class Wrapper[T] 
    object Wrapper { 
    def apply[T](implicit w: Wrapper[T]): Wrapper[T] = w 
    } 
    trait IO[In] { 
    type Out 
    } 
    implicit def decoder[In]: Wrapper[IO[In] {type Out = String}] = null 

//client code 
    Wrapper[IO[String]] 
} 

例2 - これはないのに対し:

object ImplicitWrappedTraitWithType { 
    class Wrapper[T] 
    object Wrapper { 
    def apply[T](implicit w: Wrapper[T]): Wrapper[T] = w 
    } 
    trait IO[In] { 
    type Out 
    } 
    implicit def decoder[In]: Wrapper[IO[In]] = null 

//client code 
    Wrapper[IO[String]] 
} 

クライアントコードではOutのタイプはわかりませんが、IOというインスタンスをWrapper(コードは表示されていません)から抽出すると、そのインスタンスにアクセスできるようにする必要があります。

Outパラメータをクライアントコードで見えるように保持しながら、これをコンパイルするにはどのように変更する必要がありますか。

+1

* Outのタイプがわからないのですが、WrapperからIOのインスタンスを抽出するときにアクセスできる必要があります。*しかし、IO [T]。アウト。私は問題を理解しているかどうか分からない。 –

+1

@YuvalItzchakovは、2番目の例の「Out」は制約されていません。 –

+1

@ Jasper-M拘束されていないことがわかりましたが、OPが「可視性」について話しているようにしたいとは思っていません。私は彼が何を意味するのか理解しようとしています。 –

答えて

3

コードに対して2回のマイナーな編集が​​必要です。

trait Wrapper[+T] { 
    def unwrap: T 
} 

object Wrapper { 
    def apply[T](implicit w: Wrapper[T]): w.type = w 
} 

trait IO[In] { 
    type Out 

    def out: Out 
} 

implicit def decoder[In]: Wrapper[IO[In] {type Out = String}] = new Wrapper[IO[In] {type Out = String}] { 
    override def unwrap: IO[In] {type Out = String} = new IO[In] { 
    override type Out = String 
    override val out: Out = "yeah" 
    } 
} 

val wrap = Wrapper[IO[String]] 
val io = wrap.unwrap 
val out: String = io.out 

最も重要なのはw.typeapplyメソッドの戻り値の型を変更することです。そうすれば、フルタイプのw(すべての細分化を含む)が保持されます。返品タイプとしてWrapper[T]と書かれた場合、と等しいTWrapper[T]を尋ねると、Wrapper[IO[String]]となり、{type Out = String}のような余分な知識はすべて失われます。

第2:val io: IO[String] = wrap.unwrapの中では、ioIO[String]です。再び、すべての余分な知識は失われます。だから、コンパイラにはioの型を推測させてください。

もう1つ:WrapperTに共変にしたくない場合は、分散注釈をそのまま残して、applyメソッドを変更することができます。コンパイラは、まだそれはあなたがWrapper.apply[IO[String]]を呼び出す場合ためIO[String]のサブタイプを見るために持って知っている方法

trait Wrapper[T] { 
    def unwrap: T 
} 

object Wrapper { 
    def apply[T](implicit w: Wrapper[_ <: T]): w.type = w 
} 

IO[String]{type out = String}IO[String]のサブタイプであるため、等しくありません。

+0

Spot on。ありがとう:) – eirirlar

1

はあなたが達成しようとしているかは明らかではない(この製剤は不明である場合はコメントしてください)、それはあなたの問題を解決できますか? それのための暗黙的なデコーダを検索しようとしたとき、私はOutタイプ上の任意の制限を置かないだろう

object ImplicitWrappedTraitWithType { 
    class Wrapper[-T] 
    object Wrapper { 
    def apply[T](implicit w: Wrapper[T]): Wrapper[T] = w 
    } 
    trait IO[In] { 
    type Out 
    } 
    implicit def decoder[In]: Wrapper[IO[In]] = null 


} 
import ImplicitWrappedTraitWithType._ 

trait IOString[In] extends IO[In] { 
    type Out = String 
} 
//client code 
Wrapper[IOString[Int]] 

(ラッパーで-Tを注意してください)。

ユーザが独自のデコーダを定義しているかどうかにかかわらず、InOutは気にしないか、いくつかの基本的なデコーダがあり、それを提供します。IO [Int、String]、IO [Int、Boolean ]など

+0

-Tはコンパイルに関して何もしませんでした。しかし、それは私に+ Tも試してみました。私は質問を少し更新していますが、私の問題には解決策がないと思われ始めています。 – eirirlar

+0

その間にコードを変更した可能性があります。私が少しリファクタリングしたここに投稿した例は、Tか+ Tでは動作せず、-Tでしか動作しません。 とにかく、私はあなたが別のルートをとって、よりよいアプローチを見つけたのを見ます。楽しむ! ;-) – Renato

関連する問題