2015-10-01 29 views
5

はのは、次のことを想定してみましょう:Scalaの型消去問題

class Wrapper1 { 
    case class Condition(test: String) 
} 
object Wrapper1 extends Wrapper1 

class Wrapper2 { 
    case class Condition[A](test: String) 
} 
object Wrapper2 extends Wrapper2 


class Test 
    type T = // whatever 

    def test(fn: T => Wrapper1.Condition): X 
    def test[R](fn: T => Wrapper2.Condition[R]): X 
} 

問題は、型消去のこれらのメソッドは、消去後、まったく同じタイプを持っていることです。それは言うと第二の署名を変更するのは簡単です:

def test[R](fn: T => Wrapper2.Condition[R])(implicit ev: R =:= R): X 

しかし、それはコンパイラが混乱し、他の場所でtest方法を使用することは不可能です。多くの設計上の理由から、私はこのメソッドの名前の一貫性を維持しようとしています。これを成功させる方法はありますか?

答えて

0

それをうまくすることがあります。私が後にしたのは、条件付きでHListに追加する方法でした。基本的に同じメソッドの複数のオーバーロードは、異なる種類のHListを返すため、共存する必要がありました。

1つのメソッドしか持たないためには、メソッドの最終的な署名がどのように表示されるかを決定するために引数が必要です。

それでは、次のことを想定してみましょう、test方法は

def test[RR](arg: Type1[RR]): Wrapper[RR :: ExistingHList] 

または、それぞれを返すために持っていた:

def test(arg: Type2): Wrapper[ExistingList] 

同じ方法でかどうか、引数に応じて、Hlistに追加する必要があります一定の条件を満たした。この修正はshapeless.ops.hlist.Prependを使用するのと同じくらい些細なものでしたが、デフォルトではHNilをhlistに追加しようとすると、既存のHListが返されます。

Type2の引数を返すか、HNilを返すか暗黙的にHNilとなる何かに変換します。具体的に

:条件関数は、関数が終了戻り値の型を変更する必要がない状況のためWrapper[HNil]を返します場合

class Wrapper[PS <: HList] { 
    def test[ 
     RR, 
     HL <: HList, 
     Out <: HList 
    ](
     condition: T => Wrapper[HL] 
    )(implicit prepend: Prepend.Aux[HL, PS, Out]): Wrapper[Out[ 
    } 

このアプローチは動作します。変更を行う機能は、単独で独自にHListを独自に構築できます。

0

が、これはScala double definition (2 methods have the same type erasure)

私の提案の重複しないようです...ただ、一つの方法最後に

def test[Cond: TypeTag](fn: T => Cond): X = { 
    if(typeOf[T] <:< typeOf[Wrapper1.Condition]) ... 
    else if(typeOf[T] <:< typeOf[Wrapper2.Condition[_]) ... 
    else ... 
} 
関連する問題