0
votes

My problem is that i want to mix in traits to some existing object instance

instead of doing

sealed trait Type
trait A extends Type
trait B extends Type

case class Basic(int, bool)

val someInt = 2
val someBool = False
val someType = "a"

someType match {
 case "a" => new Basic(someInt, someBool) with A
 case "b" => new Basic(someInt, someBool) with B
}

i would like to do new Basic() only once and then add somehow A and B

Is it possible to do it somehow with Shapeless ? I was hoping to be able to use Generic to get a HList, add the marker trait info in it, and convert it back to what would be a Basic with the trait attached. But I don't actually see how that would be possible with HList.

1

1 Answers

0
votes

For example you can define a Poly.

import shapeless.Poly1

object myPoly extends Poly1 {
  implicit val aCase: Case.Aux[A, Basic with A] = at(_ => new Basic() with A)
  implicit val bCase: Case.Aux[B, Basic with B] = at(_ => new Basic() with B)
}

myPoly(new A {}) 
myPoly(new B {}) 

I guess HList is irrelevant here since Generic transforms Type into a coproduct rather than HList.

import shapeless.{:+:, CNil, Generic}

sealed trait Type
case class A() extends Type
case class B() extends Type

implicitly[Generic.Aux[Type, A :+: B :+: CNil]]

You can use Poly and singleton types:

import shapeless.{Poly1, Witness}
import shapeless.syntax.singleton._

sealed trait Type
trait A extends Type
trait B extends Type

case class Basic(int: Int, bool: Boolean)

val someInt: Int = 2
val someBool: Boolean = false
val someType: String = "a"

object myPoly extends Poly1 {
  implicit val aCase: Case.Aux[Witness.`"a"`.T, Basic with A] = at(_ => new Basic(someInt, someBool) with A)
  implicit val bCase: Case.Aux[Witness.`"b"`.T, Basic with B] = at(_ => new Basic(someInt, someBool) with B)
}

myPoly("a".narrow)
myPoly("b".narrow)
//  myPoly("c".narrow) // doesn't compile