2011-07-09 15 views
4

私はスカラにとって非常に新しく、スカラー固有のパターンを適応させることは進んでいます。 目的は、メッセージの処理とメッセージ生成を分けることです。メッセージ処理を表す基本共変パラメータ型があります。特定の実現は、通常のミックスインによって、または基礎をなすプロトコルを混合することによって組み合わせることができる。同一のパラメータ化された型を持つスカラ混合物

requirmentsには、次のとおりです。

  1. は(私はクリーンなサンプルコードが付属してきた愚かな過ち

を防ぐために、タイプセーフである可能

  • としてsimapleとして拡張定義と使用の両方を含む):

    trait Protocol 
    
    trait Handler [+proto <: Protocol] { 
        def handle : PartialFunction[Protocol,Unit] 
        /* can not name the actual protocol type since handler for a subtype also fully supports handling supertype 
    besides any message extends other subtype ot the supertype since the scala use matching with case classes 
    and these algebraic type realization is seemed excluded from strait scala type system 
        */ 
    } 
    
    /* 
    ============== 
    using scenario 
    ============== 
    */ 
    
    trait SumMsg extends Protocol 
    case class Sum(op : Int) extends SumMsg 
    case class Sub(op : Int) extends SumMsg 
    
    trait ProdMsg extends Protocol 
    case class Mul(op : Int) extends ProdMsg 
    case class Diff(op : Int) extends ProdMsg { 
        require (0 != op, "Division by zero is not permited") 
    } 
    
    /* stackable traites */ 
    trait NullHandler { 
        def handle : PartialFunction[Protocol,Unit] = { case _ => {} } 
    } 
    
    trait SumHandler extends Handler [SumMsg] with NullHandler{ 
        var store : Int 
        abstract override def handle : PartialFunction[Protocol,Unit] = ({ 
    case Sum(op) => { this.store += op} 
    case Sub(op) => { this.store -= op} 
        }: PartialFunction[Protocol,Unit]) orElse super.handle 
    } 
    
    trait MulHandler extends Handler [ProdMsg] with NullHandler{ 
        var store : Int 
        abstract override def handle : PartialFunction[Protocol,Unit] = ({ 
    case Mul(op) => {this.store *= op} 
    case Diff(op) => {this.store /= op} 
        }: PartialFunction[Protocol,Unit]) orElse super.handle 
    } 
    
    /* concrete classes */ 
    class SumAccum (var store: Int) extends SumHandler 
    
    class MulAccum (var store: Int) extends MulHandler 
    
    class ArithmAccum (var store: Int) extends SumHandler with MulHandler 
    
    /* producers */ 
    class ProduceSums (val accum : Handler [SumMsg]) { 
        var state : Boolean = true 
        def touch() = if (this.state) 
    { 
        this.state = false 
        this.accum.handle(Sum(2)) 
    } else { 
        this.state = true 
        this.accum.handle(Sub(1)) 
    } 
    } 
    
    class ProduceProds (val accum : Handler [ProdMsg]) { 
        var state : Boolean = true 
        def touch() = if (this.state) 
    { 
        this.state = false 
        this.accum.handle(Mul(2)) 
    } else { 
        this.state = true 
        this.accum.handle(Diff(2)) 
    } 
    } 
    
    /* tying together via cake pattern */ 
    trait ProtocolComp { 
        type Proto <: Protocol 
    } 
    
    trait ProducerComp { this: ProtocolComp => 
        type ProducerT <: {def touch()} 
        def getProducer(accum : Handler[Proto]) : ProducerT 
    } 
    
    trait HandlerComp { this: ProtocolComp => 
        type HandlerT <: Handler[Proto] 
        def getHandler(store:Int) : HandlerT 
    } 
    
    trait AppComp extends ProtocolComp with ProducerComp with HandlerComp { 
        val initStore = 1 
        def test() { 
    val handler = getHandler(initStore) 
    val producer = getProducer(handler) 
    producer.touch() 
        } 
    } 
    
    /* different examples of compositions */ 
    
    /* correct usage */ 
    
    object One extends AppComp{ 
        override type Proto = SumMsg 
        override type ProducerT = ProduceSums 
        override type HandlerT = SumAccum 
        override def getProducer(accum : Handler[Proto]) = new ProduceSums(accum) 
        override def getHandler(store : Int) = new SumAccum(store) 
    } 
    
    object Two extends AppComp{ 
        override type Proto = SumMsg 
        override type ProducerT = ProduceSums 
        override type HandlerT = ArithmAccum 
        override def getProducer(accum : Handler[Proto]) = new ProduceSums(accum) 
        override def getHandler(store : Int) = new ArithmAccum(store) 
    } 
    
    object Three extends AppComp{ 
        override type Proto = SumMsg with ProdMsg 
        override type ProducerT = ProduceSums 
        override type HandlerT = ArithmAccum 
        override def getProducer(accum : Handler[Proto]) = new ProduceSums(accum) 
        override def getHandler(store : Int) = new ArithmAccum(store) 
    } 
    
    /* incorrect usage 
    static type checking protects from some kind of logic errors 
    */ 
    
    object Four extends AppComp{ 
        override type Proto = SumMsg 
        override type ProducerT = ProduceProds 
        override type HandlerT = SumAccum 
        override def getProducer(accum : Handler[Proto]) = new ProduceProds(accum) 
        override def getHandler(store : Int) = new SumAccum(store) 
    } 
    
    Scalaのケースクラスの代わりalegraic種類を使用するために可能な限り型保証を通り、まだ私は、組み合わせて拡張シンプルで柔軟なシステムを構築しました

    mixed.scala:140: error: type mismatch; 
    found : Handler[Four.Proto] 
    required: Handler[ProdMsg] 
        override def getProducer(accum : Handler[Proto]) = new ProduceProds(accum) 
    

    :0

    最後の例はよく入力されたと予想されるようにエラーを与えていません

    私はほとんど目標を達成しましたが、大きなスケーラ誤動作を起こしました。基本となるjvmの消去をタイプしてください。私が使用した構造は、 "with"節でパラメータ化された特性を拡張可能にしたいので、スカラにとっては違法です。私はどのようなオプションがありますかについて

    mixed.scala:53: error: illegal inheritance; 
    class ArithmAccum inherits different type instances of trait Handler: 
    Handler[ProdMsg] and Handler[SumMsg] 
    class ArithmAccum (var store: Int) extends SumHandler with MulHandler 
    

    を訴えて

    コンパイラ?私が設計したパターンを使用することはできず、使いやすさで均等な置き換えを見つける必要があります。 anoyoneが代替のソースコードソリューションを提案するかもしれない?スカラー型のプラグイン(コンパイラのために存在するように見える)か、スカラ型の型のバックエンドをjava genericsからコード生成のようなC++に変更する別のメソッドがありますか?

  • +0

    私は同じ問題があります。 F ** k JVM。 – iron9light

    答えて

    2

    あなたの問題は、JVMのタイプ消去ではなく、スカラが継承を解決するために線形化を使用することです。

    タイプパラメータ[+ proto <:Protocol]をHandlerから削除します。とにかく、ハンドルメソッドでは使用されません。それであなたの違法な相続のエラーは消え去ります。

    +0

    しかし、私はこのように型の安全性を失ってしまいます。 4番目の例は違法でコンパイルされます – ayvango

    +0

    しかし、あなたの型の安全はとにかく虚偽です。 handleメソッドは型パラメータprotoを使用していないため、Handler [A]が実際にタイプAのプロトコルを処理できることを保証することはできません。 –

    +0

    また、現在のソリューションは意図したとおりに動作するとは思われません。オブジェクト3では、タイプProto = SumMsgをProdMsgで定義します。これは、Sums *と* Prodsの両方のプロトコルしか受け入れないことを意味します。しかし、おそらくあなたが望むものはSums *または* Prodsです。私が正しく覚えていれば、Scalaでそのような型を簡単にエンコードすることはできません。 –

    関連する問題