0

同じ型パラメータでADTをenforeする方法:それがうまく働いた私はADT次いる

sealed trait Event 
case class EventA(id: Int) extends Event 
case class EventB(id: Int) extends Event 
case object EventDontCare extends Event 

object Event { 
    def test(ev: Event) = ev match { 
    case EventA(x)  => x 
    case EventB(y)  => y + 1 
    case EventDontCare => 0 
    } 
} 

val eva = EventA(10) 
println(Event.test(eva)) 

が、今、私は2つの分割タイプ、上記のようにIDとして1を使用Int、IDなどの他の使用Stringを持っている必要があります。

sealed trait GEvent[ID] 
case class GEventA[ID](id: ID) extends GEvent[ID] 
case class GEventB[ID](id: ID) extends GEvent[ID] 

object EventInt { 
    type Event = GEvent[Int] 
    type EventA = GEventA[Int] 
    type EventB = GEventB[Int] 
    case object EventDontCare extends GEvent[Int] 

    def test(ev: Event) = ev match { 
    case x: EventA  => x.id 
    case y: EventB  => y.id + 1 
    case EventDontCare => 0 
    } 
} 
object EventString {....} 

val evi = new EventInt.EventA(10) 
val evii = GEventA[Int](10) 
val evd = EventInt.EventDontCare 
println(EventInt.test(evd)) 
println(EventInt.test(evi)) 
println(EventInt.test(evii)) 

私がお願いしたいと思いますいくつかの質問があります:私はイベントの形質に型パラメータを追加しようとしました

  1. はANのすべてのメンバーに種類を注入するためのより良い方法はありますADT?私は上記のアプローチに満足していません。
  2. testメソッドのパターンマッチでは、case EventA(x) =>またはイベントcase GEventA[Int](x) =>を使用できないのはなぜですか? 同様に、newキーワードで変数eviを作成する必要がありますか?
  3. でも、私はすべての3ケースを紹介してきた、なぜコンパイラはまだ私に警告ん:

    試合は網羅できない場合があります。それは、以下の入力に失敗します: EventDontCare

    しかし、それはまだ正しく実行(DONTCAREケースのために10をプリントアウト)

答えて

1

私はあなたが正しいがある持っているものだと思います。私はあなたのADTを一緒に定義することをお勧めします(今はEventDontCareが別に定義されています)。また、基底形質Eventにはidがないため、そこに型を強制するのは無意味です。

sealed trait Event 
case class GEventA[ID](id: ID) extends Event 
case class GEventB[ID](id: ID) extends Event 
case object EventDontCare extends Event 

パターンマッチング

がメンバーにタイプを含めるには、このように書き換えることができますようだから私はあなたのADTを再度書きます。

def test(ev: Event) = ev match { 
    case GEventA(id:Int) => id 
    case GEventB(id:Int) => id + 1 
    case EventDontCare => 0 
} 

これを入力すると、あなたが言及した警告が表示されません。

最後に、タイプエイリアスで観察したことは、Scalaでの動作がどのように機能するかです。ケースクラスの型エイリアスを定義する場合、newを使用せずにエイリアスを使用してインスタンスを定義することはできません。


(オプションセクション)

ここにあなたのエンティティの残りの部分からIDを分離ADTの別の定義です。

sealed trait Event 
case object GEventA extends Event 
case object GEventB extends Event 
case object EventDontCare extends Event 
case class IdEvent[A, E <: Event](id: A, e: E) extends Event 

ここでの利点は、IDの詳細をすべてのエンティティに「汚染」させないことです。

関連する問題