object FlowDispatchApp extends App {
trait Source[S] {
def dispatch[P <% Dispatch[P]](p: P)
}
trait Dispatch[P] {
def notification
def matching
def processing
}
trait TradeType
case object SwapTrade extends TradeType
case object FutureTrade extends TradeType
case object OptionTrade extends TradeType
trait ServiceType
case object Notification extends ServiceType
case object Matching extends ServiceType
case object Processing extends ServiceType
@annotation.implicitNotFound("Service ${S} for ${T} doesn't exist.")
trait Service[T, Z, S] extends (T => Z)
object Service {
def apply[T](ss: ServiceType, t: T)
(implicit s: Service[T, Unit, ss.type]) = s(t)
def apply[T, Z](ss: ServiceType, t: T)
(implicit s: Service[T, Z, ss.type]): Z = s(t)
def apply[T](ss: ServiceType, tt: TradeType, t: T)
(implicit s: Service[T, Unit, (ss.type, tt.type)]) = s(t)
def apply[T, Z](ss: ServiceType, tt: TradeType, t: T)
(implicit s: Service[T, Z, (ss.type, tt.type)]): Z = s(t)
def unit[T](ss: ServiceType)(f: T => Unit) =
new Service[T, Unit, ss.type] {
def apply(t: T) = f(t)
}
def apply[T, Z](ss: ServiceType)(f: T => Z) =
new Service[T, Z, ss.type] {
def apply(t: T) = f(t)
}
def unit[T](ss: ServiceType, tt: TradeType)(f: T => Unit) =
new Service[T, Unit, (ss.type, tt.type)] {
def apply(t: T) = f(t)
}
def apply[T, Z](ss: ServiceType, tt: TradeType)(f: T => Z) =
new Service[T, Z, (ss.type, tt.type)] {
def apply(t: T) = f(t)
}
}
implicit lazy val m = Service.unit[String](Matching) {
(t: String) => println("match : " + t)
}
implicit lazy val spsw = Service.unit[String](Processing, SwapTrade) {
(t: String) => println("processing swap : " + t)
}
implicit class SS(val s: String) extends Source[String] {
def dispatch[P <% Dispatch[P]](p: P) {
s match {
case "notify" => p.notification
case "match" => p.matching
case _ => p.processing
}
}
}
implicit class SD(val t: String) extends Dispatch[String] {
def notification {
println("notify: " + t)
}
def matching {
Service[String](Matching, t)
}
def processing {
t match {
case "swap" => Service[String](Processing, SwapTrade, t)
case "future" => //Service[String](Processing, FutureTrade, t)
case "option" => //Service[String](Processing, OptionTrade, t)
case _ =>
}
}
}
"processing" dispatch "swap"
"match" dispatch "future"
}