Scala implicits and overrides problems - scala

Here is my problem:
trait Caller {
type EntityType
def parseEntity(entity: String): EntityType
}
trait IntCaller extends Caller {
implicit def strToInt(s: String) = s.toInt
override type EntityType = Int
override def parseEntity(entity: String): EntityType = entity
}
trait DoubleCaller extends Caller {
implicit def strToDouble(s: String) = s.toDouble
override type EntityType = Double
override def parseEntity(entity: String): EntityType = entity
}
object main {
def main(args: Array[String]): Unit = {
val intCaller = new IntCaller{}
val doubleCaller = new DoubleCaller{}
println("Result is: " + intCaller.parseEntity("5"))
println("Result is: " + doubleCaller.parseEntity("5.0"))
}
}
As you can see I keep repeating the code for: parseEntity method. If I wanted to add a FloatCaller I would have to rewrite parseEntity even though its implementation would be the same.
How can I write the implentation of the parseEntity in the Caller, so that I don't have to write the same code in the child traits again and again?
Disclaimer:
This is a simplification of a real problem I have with SprayJsonSupport from akka.http.scaladsl.marshallers.sprayjson.

You would be better off using a factory method that can build instances of a Caller given a conversion function. The only thing that's different between IntCaller and DoubleCaller is toInt and toDouble (and the types, of course).
trait Caller {
type EntityType
def parseEntity(entity: String): EntityType
}
object Caller {
def apply[A](f: String => A): Caller = new Caller {
type EntityType = A
def parseEntity(entity: String): EntityType = f(entity)
}
}
scala> val IntCaller = Caller(_.toInt)
scala> IntCaller.parseEntity("123")
res1: IntCaller.EntityType = 123
scala> val DoubleCaller = Caller(_.toDouble)
scala> DoubleCaller.parseEntity("1.23")
res2: DoubleCaller.EntityType = 1.23
If you want to keep using inheritance, then continue to force the sub-classes or traits to implement the conversion with parseEntity. It's not really necessary to using implicit conversions, though. The only reason it appears that there is repeated code is because the implicit conversion makes parseEntity look the same for each implementation, even though it's really not (because it needs to resolve a different implicit).
trait Caller {
type EntityType
def parseEntity(entity: String): EntityType
}
trait IntCaller {
type EntityType = Int
def parseEntity(entity: String): EntityType = entity.toInt
}

Related

Group TypeClass instances by type parameter

Suppose, I have 2 typeclasses:
trait Foo[A] {
...
}
trait Bar[A] {
...
}
and then I collect their instances into collections:
val seqFoo : Set[Foo[_]] = ...
val seqBar : Set[Bar[_]] = ...
is there a way to combine this seqs into something like this:
val fooBar = (Foo[Int],Bar[Int]), ... , (Foo[String],Bar[String])
Maybe pattern matching function or type tags is an answer, but I believe this case should have more straightforward solution
For example you can make your type classes abstract classes rather than traits (then they can have parameters), add implicit TypeTag parameters, and make groupBy for your collections.
import scala.reflect.runtime.universe.{TypeTag, Type}
// type class
abstract class Foo[A](implicit val ttag: TypeTag[A]) {
def foo(): String // dummy method just to distinguish instances upon checking
}
// instances
object Foo1 {
implicit val intFoo: Foo[Int] = new Foo[Int]() {
override def foo(): String = "Foo1.intFoo"
}
implicit val strFoo: Foo[String] = new Foo[String]() {
override def foo(): String = "Foo1.strFoo"
}
}
object Foo2 {
implicit val intFoo: Foo[Int] = new Foo[Int]() {
override def foo(): String = "Foo2.intFoo"
}
implicit val boolFoo: Foo[Boolean] = new Foo[Boolean]() {
override def foo(): String = "Foo2.boolFoo"
}
}
object Foo3 {
implicit val intFoo: Foo[Int] = new Foo[Int]() {
override def foo(): String = "Foo3.intFoo"
}
implicit val strFoo: Foo[String] = new Foo[String]() {
override def foo(): String = "Foo3.strFoo"
}
implicit val boolFoo: Foo[Boolean] = new Foo[Boolean]() {
override def foo(): String = "Foo3.boolFoo"
}
}
val seqFoo : Set[Foo[_]] = Set(Foo1.intFoo, Foo1.strFoo, Foo2.intFoo, Foo2.boolFoo, Foo3.intFoo, Foo3.strFoo, Foo3.boolFoo)
val grouped: Map[Type, Set[Foo[_]]] = seqFoo.groupBy(_.ttag.tpe)
// checking that instances are grouped by type
grouped.view.mapValues(_.map(_.foo())).foreach(println)
//(Int,HashSet(Foo3.intFoo, Foo1.intFoo, Foo2.intFoo))
//(String,HashSet(Foo1.strFoo, Foo3.strFoo))
//(Boolean,HashSet(Foo2.boolFoo, Foo3.boolFoo))
Simlarly you can do groupBy for Bar and then do whatever you want with Map[Type, Set[Foo[_]]] and Map[Type, Set[Bar[_]]]. For example merge the Maps
val grouped: Map[Type, Set[Foo[_]]] = ???
val grouped1: Map[Type, Set[Bar[_]]] = ???
val merged: Map[Type, (Set[Foo[_]], Set[Bar[_]])] =
(grouped.keySet union grouped1.keySet)
.map(tpe => tpe -> (grouped(tpe), grouped1(tpe)))
.toMap
I'll copy from my comment. Instances of type classes are intended to be resolved automatically (via implicit resolution) by compiler at compile time. Collecting the instances manually seems weird, so does collecting them at runtime.
My typeclasses instances implement decoder/encoder logic. Also they contain some meta information (name particularly). So i would like to check name-to-type accordance and generate unique names, based on how many instances have same name but different type parameter.
Although names of implicits can sometimes make impact on implicit resolution (1 2 3 4), normally you shouldn't be interested much in names of implicits, nor in name-to-type correspondence. Maybe you should provide some code snippet so that we can understand your setting and goals. Maybe what you need can be done at compile time and/or automatically.
Alternatively, if you prefer to keep type classes traits or you can't modify their code, you can use magnet pattern (1 2 3 4 5 6 7 8)
trait Foo[A] {
def foo(): String
}
implicit class Magnet[F[_], A: TypeTag](val inst: F[A]) {
def tpe: Type = typeOf[A]
}
val seqFoo = Set[Magnet[Foo, _]](Foo1.intFoo, Foo1.strFoo, Foo2.intFoo, Foo2.boolFoo, Foo3.intFoo, Foo3.strFoo, Foo3.boolFoo)
val grouped: Map[Type, Set[Magnet[Foo, _]]] = seqFoo.groupBy(_.tpe)
// checking that instances are grouped by type
grouped.view.mapValues(_.map(_.inst.foo())).foreach(println)
//(String,HashSet(Foo1.strFoo, Foo3.strFoo))
//(Int,HashSet(Foo3.intFoo, Foo1.intFoo, Foo2.intFoo))
//(Boolean,HashSet(Foo2.boolFoo, Foo3.boolFoo))
Using the "Prolog in Scala" to find available type class instances

How to return subtype of a generic trait in scala?

I am trying to create a factory pattern, and the return type is a parametrized trait, and the actual return type will be a subtype of that trait, but I do not know the generic type beforehand, so I don't know how to specify the return type. A simplified version is like this:
trait Mapper[T] {
def createMap(a: T, b: T): T
}
class MapperA extends Mapper[String]{
override def createMap(a: String, b: String): String = {
a + b
}
}
class MapperB extends Mapper[Int]{
override def createMap(a: Int, b: Int): Int = {
a + b + b + b
}
}
def factory(typeOfMapper: String): Mapper = {
typeOfMapper match {
case "mapperA" => new MapperA()
case "mapperB" => new MapperB()
}
}
val mapper = factory("mapperA")
This will give me and error of
trait Mapper takes type parameters
but I do not know the generic type beforehand. What should the return type be for the factory method here?
Well, you could return Mapper[_] ... that will compile, but isn't really very useful, as pointed out in the comments: you won't be able to use the returned value in any meaningful way, because actual type of create will be unknown.
If different instances of your mapper will always have different type parameters (at least, within the same scope), then a neat solution would be using implicits:
object Mapper {
implicit def strMapper: Mapper[String] = new MapperA
implicit def intMapper: Mapper[Int] = new MapperB
}
Then everywhere you have these visible, you can just do:
val m1: Mapper[String] = implicitly[Mapper[String]]
val m2: Mapper[Int] = implicitly[Mapper[Int]]
You could also write your factory function (though, I am not sure why you'd want to) like this:
def mapperFactory[T: Mapper] = implicitly[Mapper[T]]
and use it like this:
val m: Mapper[String] = mapperFactory
or like this
def intMapper = mapperFactory[Int]
If you want different mappers for the same type parameter, it's basically the same idea, except it does't look as neat without implicits. The key is different factories for different types:
class Mapper {
def str(`type`: String): Mapper[String] = `type` match {
case "foo" => FooMapper()
case "bar" => BarMapper()
}
def int(`type`: String): Mapper[Int] = `type` match {
case "baz" => BazMapper()
case "bak" => BakMapper()
}
}
val fooMapper = Mapper.str("foo")
val bakMapper = Mapper.int("bak")

Type Class for Related Types

Let's say we have the following traits:
trait MyValue
object MyValue {
case class MyBoolean(record: Boolean) extends MyValue
case class MyLong(record: Long) extends MyValue
}
trait MyValueExtractor[T] {
def apply(record: T): Option[MyValue]
}
trait MyThing[T] {
def name: String
def myValueExtractor: MyValueExtractor[T]
def myValue(record: T): Option[MyValue] = myValueExtractor(record)
}
What I want is something like this but without the second type parameter.
Note: I can't actually update the MyThing trait; I'm just using this as an illustration of the intended functionality.
trait MyThing[T, U] {
def name: String
def myValueExtractor: MyValueExtractor[T]
def myValue(record: T): Option[MyValue] = myValueExtractor(record)
def myRelatedValue(record: T): Option[U]
}
I'm wondering if I could use the type class pattern to help solve this (i.e., import some rich class that implicitly gives me a myRelatedValue method)?
Here's the rub. Every time T (above) is MyValue.MyBoolean, U must be a String. Every time T is MyValue.MyLong, U must be a Double. In other words, there's a sort of underlying mapping between T and U.
Is there a good way to do this using type class?
Sure. You just need to define some Mapping typeclass with implementations for your desired pairs of types. Then MyThing can have a method that takes an implicit typeclass instance and simply invokes its method.
Here's the code (I removed the unneeded details)
// types
case class MyBoolean(record: Boolean)
case class MyLong(record: Long)
// trait which uses the Mapping typeclass
trait MyThing[T] {
def myRelatedValue[U](record: T)(implicit ev: Mapping[T, U]): Option[U] = ev.relatedValue(record)
}
// typeclass itself
trait Mapping[T, U] {
def relatedValue(record: T): Option[U]
}
object Mapping {
implicit val boolStringMapping = new Mapping[MyBoolean, String] {
def relatedValue(record: MyBoolean) = Some(record.record.toString)
}
implicit val longDoubleMapping = new Mapping[MyLong, Double] {
def relatedValue(record: MyLong) = Some(record.record)
}
}
// usage
val myBoolThing = new MyThing[MyBoolean] {}
val myLongThing = new MyThing[MyLong] {}
val myStringThing = new MyThing[String] {}
myBoolThing.myRelatedValue(MyBoolean(true)) // Some(true)
myLongThing.myRelatedValue(MyLong(42L)) // Some(42.0)
myStringThing.myRelatedValue("someString") // error: could not find implicit value
Note that e.g. myBoolThing.myRelatedValue(MyBoolean(true)) will yield a type Option[U]. However, since myRelatedValue is parameterized, you can help the compiler and invoke it as myBoolThing.myRelatedValue[String](MyBoolean(true)), in which case you will obtain an Option[String]. If you try something other than String for MyBoolean, you will get an error.

Why does the use of typed variable make this code work

This works
trait SomeTrait {
type T
def write2( s: String): T
}
case class C() extends SomeTrait {
type T = String
override def write2(s:String): T = s }
But this does not
trait SomeTrait {
def write2[T]( s: String): T
}
case class C() extends SomeTrait {
override def write2(s: String): String =s }
To my reasoning, they ..seem similar. Why specifically does the compiler give a "method does not override anything" error? IS there a way of making this work?
If you use this definition:
trait T {
def write2[T]( s: String): T
}
Consider some client using this trait. For example:
def doSomething(t: T): Unit = {
val s: String = t.write2[String]("hello")
val n: Int = t.write2[Int]("world")
val d: Double = t.write2[Double]("!")
println(s + n.toString + d.toString)
}
I don't know what the values of s, n, and d would be, but in theory that would be a perfectly valid usage of the trait, from the compiler's perspective. So in order to truly override that write2[T] method, you would have to provide valid behavior for all possible types T.
Compare that to:
trait T2 {
type T
def write2( s: String): T
}
Or even:
trait T3[T] {
def write2(s: String): T
}
Then when callers use it:
def doSomething(t: T2): Unit = {
val x = t.write2("hello") // always returns type t.T
}
def doSomething[T](t: T3[T]): Unit = {
val x = t.write2("hello") // always returns type T
}
There's only one possible type that can be returned, once you have a specific instance of that trait. So to override that method, you need only override the behavior for that one type.
Your trait definition in the second snippet does not mean that implementations of it must have a method write2 for some type T, but that it must have a method write2 which takes a type parameter T.
That means that, if you have a value v: SomeTrait, you should be able to do
val stringed: String = v.method2[String]("foo")
val inted: Int = v.method2[Int]("foo")
This compiles:
trait T {
def write2[T]( s: String): T
}
case class C() extends T {
override def write2[T](s: String): T =s.asInstanceOf[T]
}
write2 returns a T, not a String (hence the reason why your second override does not work and the necessity in the code above for the ugly cast)

returning different return types in scala

Is there a way to return different return types from a single method in scala?
For example, if I have a load() method, I would like to return different data types depending on the object that called this method.
def load(path: String):<return type>
{
// if this instance is of type "type1", do some processing on this object,
// and return object of type "type1"
// else if this instance is of type "type2", do some processing on this object,
// and return object of type return "type2"
}
If I understand correctly what you want, F-bounded polymorphism may work for you:
trait Base[T <: Base[T]] {
def load(path: String): T
}
class Type1 extends Base[Type1] {
override def load(path: String): Type1 = new Type1 // provisional implementation
}
class Type2 extends Base[Type2] {
override def load(path: String): Type2 = new Type2
}
Then load will return the type of the current object. Note the result types in those expressions:
new Type1().load(path)
scala> res2: Type1 = Type1#744f0e0b
new Type2().load(path)
scala> res3: Type2 = Type2#77988c45
You can use scala's Either:
def load(path : String) : Either[Type1, Type2] = {
this match {
case t1 : Type1 => Left(someProcessing(t1))
case t2 : Type2 => Right(someOtherProcessing(t2))
}
}
As others stated, you can use
You can use scala's Either
just keep in mind that every method that invokes your method, will need to check which of the types it is returning (using .map or pattern matching). Either is usually used like Either[ErrorType, NormalType] btw, but of course you can use it however you want
scala cats library has other alternative: http://eed3si9n.com/herding-cats/Xor.html
and of course, scalaz also provides an alternative: http://appliedscala.com/blog/2016/scalaz-disjunctions/
As a last resort, don't you can define your own "Either"
If your requirement is as simple as returning some instance of the type of context instance... ie this then you can just do this,
class A() {
def omg(s: String): this.type = new A()
}
And if inheritence is involved,
trait A {
type omgType
def omg(s: String): omgType
}
class B() extends A {
override type omgType = this.type
override def omg(s: String): omgType = new B()
}
class C() extends A {
override type omgType = this.type
override def omg(s: String): omgType = new C()
}
But if you want more generality then you may want to read the following and apply it there,
The easiest way will be to take inspiration from the magnet pattern which was heavily used in Spray.
We can leverage the inspiration to build our custom solution, remember it is neither pure magnet pattern nor is path dependent type approach. Its a hacky cocktail of both.
So... lets say you want your def process to be able to support input parameters of type Int and String and finally return the respective result.
You will need to define implicit magnets for these types,
trait ProcessMagnet {
type Input
type Result
def input: Input
def process: Result
}
object ProcessMagnetProvider {
implicit def stringToStringProcessMagnet(string: String): ProcessMagnet = new ProcessMagnet {
override type Input = String
override type Result = String
override def input: Input = string
// define this for your doing...
override def process: Result = input + "_omg"
}
//... add for all your inputs
implicit def intToIntProcessMagnet(int: Int): ProcessMagnet = new ProcessMagnet {
override type Input = Int
override type Result = Int
override def input: Input = int
// define this for your doing...
override def process: Result = input + 1
}
}
def process[T](t: T)(implicit pmConverter: T => ProcessMagnet): ProcessMagnet = pmConverter(t)
// now just import our implicit magnets...
import ProcessMagnetProvider._
val intResult: Int = process(5).process.asInstanceOf[Int]
val stringResult: String = process("omg").process.asInstanceOf[String]
what about factory method and just defining a trait loadable eg:
trait Loadable {
def load(path: String): Loadable
}
class Type1 extends Loadable {
def load(path: String): Type1 = this
}
class Type2 extends Loadable {
def load(path: String): Type2 = this
}
object Main {
def test(): Loadable = {
new Type1().load("path")
}
def main(args: Array[String]): Unit = {
println(test().getClass)
}
}