Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import shapeless._
- trait Consume[Src, Snk] {
- def consume(source: Src, sink: Snk): Unit
- }
- trait ConsumeGeneric2{
- implicit def allConsumeGeneric[Src <: Source, Snk <: Sink, SinkAll <: Coproduct](
- implicit
- gen: Generic.Aux[Snk, SinkAll],
- consume: AllConsume[Src, SinkAll]
- ): Consume[Src, Snk] =
- (src, snk) => consume.consume(src, gen.to(snk))
- }
- trait ConsumeGeneric1 extends ConsumeGeneric2 {
- implicit def consumeAllGeneric[Src <: Source, Snk <: Sink, SrcAll <: Coproduct](
- implicit
- gen: Generic.Aux[Src, SrcAll],
- consume: ConsumeAll[SrcAll, Snk]
- ): Consume[Src, Snk] =
- (src, snk) => consume.consume(gen.to(src), snk)
- }
- object Consume extends ConsumeGeneric1 {
- def apply[Src, Snk](implicit consume: Consume[Src, Snk]): Consume[Src, Snk] = consume
- implicit def consumeDirect[Src <: Source, Snk <: Sink, O, I](implicit ev1: Src <:< Source.Aux[O], ev2: Snk <:< Sink.Aux[I], ev3: O => I): Consume[Src, Snk] =
- (src, snk) => (snk: Sink.Aux[I]).offer((src: Source.Aux[O]).produce())
- }
- trait ConsumeAll[Srcs <: Coproduct, Snk] extends Consume[Srcs, Snk]
- object ConsumeAll {
- implicit def consumeCnil[Snk]: ConsumeAll[CNil, Snk] = (srcs, snk) => srcs.impossible
- implicit def consumeCons[Src <: Source, T <: Coproduct, Snk <: Sink](implicit head: Consume[Src, Snk], tail: ConsumeAll[T, Snk]): ConsumeAll[Src :+: T, Snk] = {
- case (Inl(h), snk) => head.consume(h, snk)
- case (Inr(t), snk) => tail.consume(t, snk)
- }
- }
- trait AllConsume[Srcs, Snk <: Coproduct] extends Consume[Srcs, Snk]
- object AllConsume{
- implicit def consumeCnil[Src]: AllConsume[Src, CNil] = (src, snks) => snks.impossible
- implicit def consumeCons[Src <: Source, Snk <: Sink, T <: Coproduct](implicit head: Consume[Src, Snk], tail: AllConsume[Src, T]): AllConsume[Src, Snk :+: T] = {
- case (src, Inl(h)) => head.consume(src, h)
- case (src, Inr(t)) => tail.consume(src, t)
- }
- }
- //implicitly[Int <:< Int]
- sealed trait Source {
- type Result
- def produce(): Result
- }
- object Source {
- type Aux[A] = Source {type Result = A}
- class IntSource extends Source {
- override type Result = Int
- override def produce() = 4
- }
- class LongSource extends Source {
- override type Result = Long
- override def produce() = 8
- }
- }
- sealed trait Sink {
- type Input
- def offer(result: Input): Unit
- }
- implicit class SinkOps[Snk <: Sink](val snk: Snk) /* extends AnyVal */{
- def consume[Src <: Source](src: Src)(implicit consume: Consume[Src, Snk]): Unit = consume.consume(src, snk)
- }
- object Sink {
- type Aux[R] = Sink {type Input = R}
- class BigDecimalSink extends Sink {
- override type Input = BigDecimal
- override def offer(in: BigDecimal) = println(s"bigDecimal $in")
- }
- class LongSink extends Sink {
- override type Input = Long
- override def offer(in: Input) = println(s"long $in")
- }
- class BigIntSink extends Sink {
- override type Input = BigInt
- override def offer(in: BigInt) = println(s"bigInt $in")
- }
- }
- import Source._
- import Sink._
- for {
- src <- List[Source](new IntSource, new LongSource)
- snk <- List[Sink](new LongSink, new BigIntSink, new BigDecimalSink)
- } snk.consume(src)
Add Comment
Please, Sign In to add comment