Let's say I have this:
trait FormData
case class DepartmentData(id: Long, title: String) extends FormData
and this companion object:
object DepartmentData {
def empty: DepartmentData = ???
def from(value: SomeKnownType): DepartmentData = ???
}
What I would like is to make sure that all the classes implementing the FormData Trait, have the two methods empty and from in their companion object.
I do not think we can do this directly, however try type class solution like so
trait FormData
case class DepartmentData(id: Long, title: String) extends FormData
case class EmployeeData(id: Long, title: String) extends FormData
trait SomeKnownType
trait FormDataFactory[T <: FormData] {
def empty: T
def from(value: SomeKnownType): T
}
object FormDataFactory {
def empty[T <: FormData](implicit ev: FormDataFactory[T]): T = ev.empty
def from[T <: FormData](value: SomeKnownType)(implicit ev: FormDataFactory[T]): T = ev.from(value)
implicit object fooDepartmentData extends FormDataFactory[DepartmentData] {
override def empty: DepartmentData = ???
override def from(value: SomeKnownType): DepartmentData = ???
}
implicit object fooEmployeeData extends FormDataFactory[EmployeeData] {
override def empty: EmployeeData = ???
override def from(value: SomeKnownType): EmployeeData = ???
}
}
Now call
FormDataFactory.empty[DepartmentData]
FormDataFactory.empty[EmployeeData]
Related
I am trying to build a DSL, one of the method on this DSL is parameterless and use a bounded generic type. Today I have to add a "feature" that will ideally use the same method name. However, because the only parameter is the generic one, I cannot override it with the usual way.
Is there a trick to allow the use of the same method for different generic types ?
My method looks like:
def ask[H <: Handler] = {
new CommandBuilder[H]
}
class CommandBuilder[H <: Handler] {
def toExecute[C <: H#C](command: C) = {
//...
}
}
And I would like to add:
def ask[S <: State] = {
new QueryBuilder[S]
}
class QueryBuilder[S <: State] {
def toExecute[Q <: S#Q](query: Q) = {
//...
}
}
I was thinking to pattern match a ClassTag on the type but I need strong type safety:
Query on a Handler, is not allowed. ask[State] must return QueryBuilder
Command and Query are the only supported types. The generic type of ask can only be a Handler or a State.
Maybe you could refactor your code to something like this?
sealed trait FooBar
sealed trait Foo extends FooBar {
def process(i: Int): Int
}
object Foo {
implicit final case object FooImpl extends Foo {
override def process(i: Int): Int = i + 1
}
}
sealed trait Bar extends FooBar {
def process(s: String): String
}
object Bar {
implicit final case object BarImpl extends Bar {
override def process(s: String): String = s.toUpperCase
}
}
object Test {
trait FooBarPartiallyApplied[FB <: FooBar] {
type Out
def out: Out
}
object FooBarPartiallyApplied {
type Aux[FB <: FooBar, _Out] = FooBarPartiallyApplied[FB] { type Out = _Out }
implicit final def FooPartiallyAppliedBuilder[F <: Foo]: Aux[F, FooPartiallyApplied[F]] =
new FooBarPartiallyApplied[F] {
override final type Out = FooPartiallyApplied[F]
override final val out: FooPartiallyApplied[F] =
new FooPartiallyApplied[F](dummy = true)
}
implicit final def BarPartiallyAppliedBuilder[B <: Bar]: Aux[B, BarPartiallyApplied[B]] =
new FooBarPartiallyApplied[B] {
override final type Out = BarPartiallyApplied[B]
override final val out: BarPartiallyApplied[B] =
new BarPartiallyApplied[B](dummy = true)
}
final class FooPartiallyApplied[F <: Foo](private val dummy: Boolean) extends AnyVal {
def toExecute(i: Int)(implicit foo: F): Int = foo.process(i)
}
final class BarPartiallyApplied[B <: Bar](private val dummy: Boolean) extends AnyVal {
def toExecute(s: String)(implicit bar: B): String = bar.process(s)
}
}
def ask[FB <: FooBar](implicit pa: FooBarPartiallyApplied[FB]): pa.Out =
pa.out
}
It works as expected:
Test.ask[Foo.FooImpl.type].toExecute(10)
// res: Int = 11
Test.ask[Foo.FooImpl.type].toExecute("blah")
// Type error.
Test.ask[Bar.BarImpl.type].toExecute(10)
// Type error.
Test.ask[Bar.BarImpl.type].toExecute("blah")
// res: String = "BLAH"
Is there any better design to achieve this scenario?
case class Animal()
case class Dog() extends Animal
case class Cow() extends Animal
trait BasePropertyImpl[T <: Animal] {
def property1(animal: T): T
def property2(animal: T): T
}
object DogPropertyImpl extends BasePropertyImpl[Dog] {
def property1(animal: Dog): Dog = ???
def property2(animal: Dog): Dog = ???
}
object CowPropertyImpl extends BasePropertyImpl[Cow] {
def property1(animal: Cow): Cow = ???
def property2(animal: Cow): Cow = ???
}
object AnimalImplRegistrar {
def getRegisteredAnimals: Map[String, BasePropertyImpl[Animal]] = Map(
"Dog" -> DogPropertyImpl,
"Cow" -> CowPropertyImpl,
)
}
object Main {
def main(args: Array[String]): Unit = {
val animal = AnimalImplRegistrar.getRegisteredAnimals.get("Dog").get
aminal.property1(Dog())
}
}
Here what I am trying to achieve is deferent implementation say CowPropertyImpl, DogPropertyImpl , or some more different implementations, I am keeping it in a Map and in runtime based on user input I am retrieving the implementation from Map and calling the method of that Impl class
This is a good candidate for the Type Class Pattern:
sealed trait Animal
case object Dog extends Animal
case object Cat extends Animal
trait AnimalProperties[A] {
def property: A
}
object AnimalProperties {
implicit val dogProperties = new AnimalProperties[Dog.type] {
override def property: Dog.type = ???
}
implicit val catProperties = new AnimalProperties[Cat.type] {
override def property: Cat.type = ???
}
}
def f[A](a: A)(implicit ev: AnimalProperties[A]) = {
val a: A = ev.property
}
Based on the type of A (cat, dog) we get the desired properties of each animal.
I have a custom type, Value:
trait Value
object Value {
case class BooleanValue(record: Boolean) extends Value
case class LongValue(record: Long) extends Value
}
And a trait that knows how to get a Value, called GetsValue, given some input type T:
sealed trait GetsValue[T] { def apply(record: T): Option[Value] }
object GetsValue {
trait GetsBooleanValue[T] extends GetsValue[T] { override def apply(record: T): Option[Value.BooleanValue] }
trait GetsLongValue[T] extends GetsValue[T] { override def apply(record: T): Option[Value.LongValue] }
}
Notice that GetsValue is sealed, so users will only extend GetsValue.GetsBooleanValue or GetsValue.GetsLongValue.
trait Extractor[T] {
def title: String
def getsValue: GetsValue[T]
def relatedValue[U]: U = ??? // question below
}
What I want to achieve is the following:
If getsValue is a GetsValue.GetsBooleanValue[_], then return a String with the text "boo!" (i.e., U is of type String).
If getsValue is a GetsValue.GetsLongValue[_], then return a Double with the value of 1.1 (i.e., U is of type Double).
Also note that I don't want to match on getsValue's type T. I want to match irrespective of what its type T is.
I want to use type class / implicits if that makes sense. Using Either is not an option for me.
Perhaps something like this would work:
First, modify GetsValue to add a type parameter that specifies the return type:
sealed trait GetsValue[T, V <: Value] { def apply(record: T): Option[V] }
object GetsValue {
trait GetsBooleanValue[T] extends GetsValue[T, Value.BooleanValue] { }
trait GetsLongValue[T] extends GetsValue[T, Value.LongValue] { }
}
Then a trait to correlate a type V to a value of U:
trait RelatedValue[V <: Value, U] {
def get: U
}
And some implicit values of that trait:
object Extractor {
implicit val boolRV = new RelatedValue[Value.BooleanValue, String] { def get = "boo!" }
implicit val longRV = new RelatedValue[Value.LongValue, Double] { def get = 1.1 }
}
Then your Extractor trait can be:
trait Extractor[T] {
type V <: Value
type U
def title: String
def getsValue: GetsValue[T, V]
def relatedValue(implicit rv: RelatedValue[V, U]): U = rv.get
}
An example implementation:
object Example extends Extractor[String] {
type V = Value.BooleanValue
type U = String
def title = "Example"
def getsValue = new GetsValue.GetsBooleanValue[String] {
def apply(s: String) = None
}
}
import Extractor._
println(Example.relatedValue)
Prints "boo!"
I try to write general apply method to serve as a factory method for child classes. What I came up with is following:
trait A
object A {
def apply[T <: A](someParam: String): T {
new T()
}
}
class B private extends A
class C private extends A
So one can create new B or C instance:
def main(args: Array[String]): Unit = {
A[B]("test")
}
Is it acceptable that trait has an accompanying object?Is there a better way to implement this?
You could:
trait A
object A {
def apply[T <: A ](someParam: String) (implicit ev: ClassTag[T]): T ={
ev.runtimeClass.newInstance().asInstanceOf[T]
}
}
But its not very useful with varying constructor's for each sub class
sealed trait A
object A {
def apply[T <: A](someParam: String)(implicit ev: T): T = {
ev
}
}
class B(n: Int) extends A
class C(n: String) extends A
object B {
implicit def defaultCons: B = new B(1)
}
object C {
implicit def defaultCons: C = new C("hi")
}
Or you could also go via combination of ClassTag approach with pattern match based on the class instead of using reflection for instantiation.
In my application I have multiple case classes and objects which are part of sealed trait hierarchy. I use them as messages in Akka.
Those classes need to be converted to user friendly form before sending through websocket.
Previously I used big pattern match to convert them in single place, but as number of types grows I would like to use implicit conversion:
object Types {
sealed trait Type
case object SubType1 extends Type
case object SubType2 extends Type
case object SubType3 extends Type
trait Converter[T] {
def convert(t: T): Int
}
}
object Implicits {
import Types._
implicit object Type1Coverter extends Converter[SubType1.type] {
override def convert(t: SubType1.type): Int = 1
}
implicit object Type2Coverter extends Converter[SubType2.type] {
override def convert(t: SubType2.type): Int = 2
}
implicit object Type3Coverter extends Converter[SubType3.type] {
override def convert(t: SubType3.type): Int = 3
}
}
object Conversion {
import Types._
def convert[T: Converter](t: T): Int = {
implicitly[Converter[T]].convert(t)
}
def convert2[T <: Type](t: T)(implicit ev1: Converter[SubType1.type], ev2: Converter[SubType2.type], ev3: Converter[SubType3.type]): Int = {
t match {
case t1#SubType1 =>
implicitly[Converter[SubType1.type]].convert(t1)
case t2#SubType2 =>
implicitly[Converter[SubType2.type]].convert(t2)
case t3#SubType3 =>
implicitly[Converter[SubType3.type]].convert(t3)
}
}
}
I would like to use them as follow:
import Types._
import Conversion._
import Implicits._
val t1 = SubType1
val x1: Int = convert(t1)
val t: Type = SubType2 // T is of type Type
//Is it possible to handle that?
//val x: Int = convert(t)
val y: Int = convert2(t)
I would love to know if there is any "magic" way to generate something like convert2 automatically without writing a macro. Maybe there is already a library which provides macro like this?
Since you have no info at compile time about t's type, you have to work at runtime.
if you put your Converters in a sealed family, you could do something like the follwing, using a technique explained in this question:
import shapeless._
trait AllSingletons[A, C <: Coproduct] {
def values: List[A]
}
object AllSingletons {
implicit def cnilSingletons[A]: AllSingletons[A, CNil] =
new AllSingletons[A, CNil] {
def values = Nil
}
implicit def coproductSingletons[A, H <: A, T <: Coproduct](implicit
tsc: AllSingletons[A, T],
witness: Witness.Aux[H]): AllSingletons[A, H :+: T] =
new AllSingletons[A, H :+: T] {
def values = witness.value :: tsc.values
}
}
trait EnumerableAdt[A] {
def values: Set[A]
}
object EnumerableAdt {
implicit def fromAllSingletons[A, C <: Coproduct](implicit
gen: Generic.Aux[A, C],
singletons: AllSingletons[A, C]): EnumerableAdt[A] =
new EnumerableAdt[A] {
def values = singletons.values.toSet
}
}
object Types {
sealed trait Type
case object SubType1 extends Type
case object SubType2 extends Type
case object SubType3 extends Type
sealed abstract class Converter[T <: Type: ClassTag] {
def convert(t: T): Int
def convertibleObjectClass = implicitly[ClassTag[T]].runtimeClass
}
object Implicits {
implicit object Type1Converter extends Converter[SubType1.type] {
override def convert(t: SubType1.type): Int = 1
}
implicit object Type2Converter extends Converter[SubType2.type] {
override def convert(t: SubType2.type): Int = 2
}
// let's pretend you FORGOT to add Type3Converter
// implicit object Type3Converter extends Converter[SubType3.type] {
// override def convert(t: SubType3.type): Int = 3
// }
}
}
object Conversion {
import Types._
val AllConverters: Map[Class[_], Converter[_ <: Type]] = implicitly[EnumerableAdt[Converter[_ <: Type]]].values
.map(c => c.convertibleObjectClass -> c).toMap
// You're sure you have all the converters here but you can't be sure you remembered to add one per subtype... you have to test it
// you are sure this cast doesn't fail anyway because of how you created the map
def findConverter[T <: Type](t: T) = AllConverters.get(t.getClass).asInstanceOf[Option[Converter[T]]]
def convert2[T <: Type](t: T): Option[Int] = findConverter(t).map(_.convert(t))
}
object Test extends App {
import Types._
import Conversion._
val t: Type = SubType2
val t2: Type = SubType3
// works, because a Converter[Subtype2.type] exists
val a: Option[Int] = convert2(t)
// returns None, because a Converter[Subtype3.type] doesn't exist
val b: Option[Int] = convert2(t2)
}