Is it possible to specify a Trait for a companion object? - scala

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

Scala, override method on generic type

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"

Scala typed trait different types Implementation keeping it in Map, not working

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.

Internal type U dependent on trait def

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!"

Accompanying object for trait in Scala

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.

Provide implicits for all subtypes of sealed type

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)
}