I want to build an interface that doesn't have any dependencies, only scala library
Let's imagine this is what i want:
iface.jar
trait jsonIface[JsValue] {
def turnJsonIntoClass[T](t: JsValue)
}
As you see it doesn't contains any imports.
Let's go to implementation:
iface_implementation1.jar
import play.api.libs.json._
trait myPlayJsonImpl extends jsonIface[JsValue] {
def turnJsonIntoClass[T](t: JsValue) { t.as[T] }
}
But this wouldn't compile because as[T] needs implicit Reads[T]
So i rewrote my iface like that:
trait jsonIface[JsValue] {
type metaInfo[T]
def turnJsonIntoClass[T](t: JsValue)(implicit meta: metaInfo[T])
}
and play json impl looks like that:
import play.api.libs.json._
trait myPlayJsonImpl extends jsonIface[JsValue] {
type conv[M] = Reads[M]
def turnJsonIntoClass[T](t: JsValue)(implicit reads: Reads[T]) { t.as[T] }
}
and json4s looks like that:
import org.json4s.JsonAST._
trait json4sImpl extends jsonIface[JValue] {
type conv[M] = Manifest[M]
def turnJsonIntoClass[T](t: JsValue)(implicit reads: Manifest[T]) { t.extract[T] }
}
This compiles but it looks cumbersome
Normally when you start to work with type-class traits you continue to do so rather than work with OOP traits:
import org.json4s.Formats
import org.json4s.JsonAST.JValue
import play.api.libs.json.{JsValue, Reads}
trait jsonIface[JsValue, T] {
def turnJsonIntoClass(t: JsValue): T
}
object jsonIface {
implicit def json4sImpl[T](implicit formats: Formats, manifest: Manifest[T]): jsonIface[JValue, T] = new jsonIface[JValue, T] {
def turnJsonIntoClass(t: JValue): T = t.extract[T]
}
implicit def myPlayJsonImpl[T](implicit reads: Reads[T]): jsonIface[JsValue, T] = new jsonIface[JsValue, T] {
def turnJsonIntoClass(t: JsValue): T = t.as[T]
}
}
or
object jsonIface {
implicit def json4sImpl[T](implicit formats: Formats, manifest: Manifest[T]): jsonIface[JValue, T] = (t: JValue) => t.extract[T]
implicit def myPlayJsonImpl[T](implicit reads: Reads[T]): jsonIface[JsValue, T] = (t: JsValue) => t.as[T]
}
Related
I'm trying to solve a problem that may not be possible in Scala.
I want to have a Trait to solve default constructors
trait Builder[T <: Buildable] {
def build(code: String): T = new T(code)
def build: T = new T("bar")
}
So extending the Trait on the companion object automatically has access to functions that creates the class with specific constructors and parameters
class A(code: String) extends Buildable
object A extends Builder[A]
Extending the Trait, the companion object has the constructors
A.build("foo")
A.build
Is this possible in Scala?
Also tried abstract classes, but hadn't had any success
trait Builder[T <: BuildableClass] {
def build(code: String): T = new T(code)
def build: T = new T("bar")
}
abstract class BuildableClass(code: String)
class A(code: String) extends BuildableClass(code)
object A extends Builder[A]
Thanks in advance
Edit: currently locked on Scala 2.12
Because of the type erasure, in ordinary code new T is allowed only for class type T, not an abstract type/type parameter.
In Scala, is it possible to instantiate an object of generic type T?
How to create an instance of type T at runtime with TypeTags
Class type required but T found
An alternative to runtime reflection (see #StanislavKovalenko's answer) is macros. new T is possible there because during macro expansion T is not erased yet.
import scala.language.experimental.macros
import scala.reflect.macros.blackbox // libraryDependencies += scalaOrganization.value % "scala-reflect" % scalaVersion.value
abstract class BuildableClass(code: String)
trait Builder[T <: BuildableClass] {
def build(code: String): T = macro BuilderMacros.buildImpl[T]
def build: T = macro BuilderMacros.buildDefaultImpl[T]
}
class BuilderMacros(val c: blackbox.Context) {
import c.universe._
def buildImpl[T: WeakTypeTag](code: Tree): Tree = q"new ${weakTypeOf[T]}($code)"
def buildDefaultImpl[T: WeakTypeTag]: Tree = q"""new ${weakTypeOf[T]}("bar")"""
}
// in a different subproject
class A(code:String) extends BuildableClass(code)
object A extends Builder[A]
A.build("foo") // scalac: new A("foo")
A.build // scalac: new A("bar")
Alternative implementations:
trait Builder[T <: BuildableClass] {
def build(code: String): T = macro BuilderMacros.buildImpl
def build: T = macro BuilderMacros.buildDefaultImpl
}
class BuilderMacros(val c: blackbox.Context) {
import c.universe._
val tpe = c.prefix.tree.tpe.baseType(symbolOf[Builder[_]]).typeArgs.head
def buildImpl(code: Tree): Tree = q"new $tpe($code)"
def buildDefaultImpl: Tree = q"""new $tpe("bar")"""
}
class BuilderMacros(val c: blackbox.Context) {
import c.universe._
val symb = c.prefix.tree.symbol.companion
def buildImpl(code: Tree): Tree = q"new $symb($code)"
def buildDefaultImpl: Tree = q"""new $symb("bar")"""
}
class BuilderMacros(val c: blackbox.Context) {
import c.universe._
val tpe = c.prefix.tree.tpe.companion
def buildImpl(code: Tree): Tree = q"new $tpe($code)"
def buildDefaultImpl: Tree = q"""new $tpe("bar")"""
}
class BuilderMacros(val c: blackbox.Context) {
import c.universe._
val tpe = symbolOf[Builder[_]].typeParams.head.asType.toType
.asSeenFrom(c.prefix.tree.tpe, symbolOf[Builder[_]])
def buildImpl(code: Tree): Tree = q"new $tpe($code)"
def buildDefaultImpl: Tree = q"""new $tpe("bar")"""
}
One of the potential solution that uses a reflection looks a bit ugly, but it works.
import scala.reflect._
trait Builder[T <: Buildable] {
def build(code: String)(implicit ct: ClassTag[T]): T =
ct.runtimeClass.getConstructors()(0).newInstance(code).asInstanceOf[T]
def build(implicit ct: ClassTag[T]): T =
ct.runtimeClass.getConstructors()(0).newInstance("bar").asInstanceOf[T]
}
trait Buildable
class A(code: String) extends Buildable {
def getCode = code
}
object A extends Builder[A]
val a: A = A.build
println(a.getCode)
The problem is that your Builder trait doesn't know anything about how to construct your instances. You can get this info from runtime with reflection or from compile time with macros.
Found a much cleaner solution to this problem without using macros / reflection / implicits
trait Buildable
trait Builder[T <: Buildable] {
self =>
def apply(code: String): T
def build: T = self.apply("foo")
def build(code: String): T = self.apply(code)
}
case class A(code: String) extends Buildable {
def getCode: String = code
}
object A extends Builder[A]
A.build("bar").getCode
A.build.getCode
I'm trying to implement a covariant return type for a method in Scala. Let's assume we have the following scenario:
class Animal
class Dog extends Animal
class Cat extends Animal
abstract class M[-T]{
def get[U <: T](): U
}
val container = new M[Animal] {
override def get[U <: Animal](): U = ???
}
How should I do that?
If you're just curious, for example you can use Shapeless
import shapeless.{Generic, HNil}
def get[U <: Animal]()(implicit generic: Generic.Aux[U, HNil]): U =
generic.from(HNil)
get[Dog] // Dog() for case class, Dog#34340fab otherwise
get[Cat] // Cat() for case class, Cat#2aafb23c otherwise
get[Nothing] // doesn't compile
get[Null] // doesn't compile
get[Cat with Dog] // doesn't compile
Or you can use a macro
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
def get[U <: Animal](): U = macro getImpl[U]
def getImpl[U: c.WeakTypeTag](c: blackbox.Context)(): c.Tree = {
import c.universe._
q"new ${weakTypeOf[U]}"
}
Or you can use runtime reflection
import scala.reflect.runtime.universe._
import scala.reflect.runtime
def get[U <: Animal : TypeTag](): U = {
val typ = typeOf[U]
val constructorSymbol = typ.decl(termNames.CONSTRUCTOR).asMethod
val runtimeMirror = runtime.currentMirror
val classSymbol = typ.typeSymbol.asClass
val classMirror = runtimeMirror.reflectClass(classSymbol)
val constructorMirror = classMirror.reflectConstructor(constructorSymbol)
constructorMirror().asInstanceOf[U]
}
(see also example with Java reflection in #KrzysztofAtłasik's answer.)
Or you just can introduce a type class and define its instances manually
trait Get[U <: Animal] {
def get(): U
}
object Get {
implicit val dog: Get[Dog] = () => new Dog
implicit val cat: Get[Cat] = () => new Cat
}
def get[U <: Animal]()(implicit g: Get[U]): U = g.get()
Alternatively, you could use reflection to create new instances. You just need to get implicit classTag:
import scala.reflect.ClassTag
class Animal
class Dog extends Animal
class Cat extends Animal
abstract class M[-T] {
def get[U <: T](implicit ct: ClassTag[U]): U
}
val container = new M[Animal] {
override def get[U <: Animal](implicit ct: ClassTag[U]): U =
//it gets no argument constructor so obviosly it will only work if your classes has no params
ct.runtimeClass.getConstructor().newInstance().asInstanceOf[U]
}
container.get[Dog]
I have a method with implicits:
def f(x: String)(implicit dispatcher: ExecutionContextExecutor, mat: ActorMaterializer) = ???
And I want to create a helper method like:
def g1(y: String) = f("uri1" + y)
def g2(y: String) = f("uri2" + y)
Of course, this cannot compile as no implicits found for parameter ex: ExecutionContext for method g.
I don't want to repeat the implicits declaration in g.
So, what's the idiomatic solution for this case?
Idiomatic solution is to repeat implicit parameters.
If you repeat the same set of implicit parameters many times then idiomatic solution is to introduce your type class (or just single implicit) instead of that set of implicits and use this type class.
Not idiomatic solution is to introduce macro annotation that will generate implicit parameter section for methods.
Sometimes you can transfer implicits to some level above
class MyClass(implicit val ec: ExecutionContext) extends ExecutionContextAware {
def f(x: String) = ???
def g(y: String) = f("xxx" + y)
}
trait ExecutionContextAware {
implicit def ec: ExecutionContext
}
or
trait MyTrait extends ExecutionContextAware {
def f(x: String) = ???
def g(y: String) = f("xxx" + y)
}
object Impl extends ExecutionContextAware {
implicit def ec: ExecutionContext = ExecutionContext.Implicits.global
}
trait ExecutionContextAware {
implicit def ec: ExecutionContext
}
Could you please also give an example with typeclass?
Suppose you have multiple type classes
trait TC1[A] {
def foo = ???
}
trait TC2[A] {
def bar = ???
}
and you have to repeat them in methods
def f[A](implicit tc1: TC1[A], tc2: TC2[A]) = ???
1. Then you can introduce your type class
trait TC[A] {
def foo
def bar
}
express it via TC1, TC2, ...
object TC {
implicit def mkTC[A](implicit tc1: TC1[A], tc2: TC2[A]): TC[A] = new TC[A] {
def foo = tc1.foo
def bar = tc2.bar
}
}
and use it
def f[A](implicit tc: TC[A]) = ???
2. Alternative approach is
trait TC[A] {
implicit def tc1: TC1[A]
implicit def tc2: TC2[A]
}
object TC {
implicit def mkTC[A](implicit _tc1: TC1[A], _tc2: TC2[A]): TC[A] = new TC[A] {
implicit def tc1: TC1[A] = _tc1
implicit def tc2: TC2[A] = _tc2
}
}
def f[A](implicit tc: TC[A]) = {
import tc._
???
}
In your example with ExecutionContextExecutor, ActorMaterializer (for example following the 2nd approach) you can introduce
trait MyImplicit {
implicit def dispatcher: ExecutionContextExecutor
implicit def mat: ActorMaterializer
}
and replace
def f(x: String)(implicit dispatcher: ExecutionContextExecutor, mat: ActorMaterializer) = ???
with
def f(x: String)(implicit mi: MyImplicit) = {
import mi._
???
}
I am trying to abstract out the json parsing logic that gets triggered for a specific type.
I started out creating a Parser trait as follows:
trait Parser {
def parse[T](payload : String) : Try[T]
}
I have an implementation of this trait called JsonParser which is:
class JsonParser extends Parser {
override def parse[T](payload: String): Try[T] = parseInternal(payload)
private def parseInternal[T:JsonParserLike](payload:String):Try[T] = {
implicitly[JsonParserLike[T]].parse(payload)
}
}
The JsonParserLike is defined as follows:
trait JsonParserLike[T] {
def parse(payload: String): Try[T]
}
object JsonParserLike {
implicit val type1Parser:JsonParserLike[Type1] = new JsonParserLike[Type1]
{
//json parsing logic for Type1
}
implicit val type2Parser:JsonParserLike[Type2] = new JsonParserLike[Type2]
{
//json parsing logic for Type2
}
}
When I try compiling the above, the compilation fails with:
ambiguous implicit values:
[error] both value type1Parse in object JsonParserLike of type => parser.jsonutil.JsonParserLike[parser.models.Type1]
[error] and value type2Parser in object JsonParserLike of type => parser.jsonutil.JsonParserLike[parser.models.Type2]
[error] match expected type parser.jsonutil.JsonParserLike[T]
[error] override def parse[T](payload: String): Try[T] = parseInternal(payload)
Not sure why the implicit resolution is failing here. Is it because the parse method in the Parser trait doesn't have an argument of type parameter T?
I tried another approach as follows:
trait Parser {
def parse[T](payload : String) : Try[T]
}
class JsonParser extends Parser {
override def parse[T](payload: String): Try[T] = {
import workflow.parser.JsonParserLike._
parseInternal[T](payload)
}
private def parseInternal[U](payload:String)(implicit c:JsonParserLike[U]):Try[U] = {
c.parse(payload)
}
}
The above gives me the following error:
could not find implicit value for parameter c: parser.JsonParserLike[T]
[error] parseInternal[T](payload)
[error]
^
Edit: Adding the session from the REPL
scala> case class Type1(name: String)
defined class Type1
scala> case class Type2(name:String)
defined class Type2
scala> :paste
// Entering paste mode (ctrl-D to finish)
import scala.util.{Failure, Success, Try}
trait JsonParserLike[+T] {
def parse(payload: String): Try[T]
}
object JsonParserLike {
implicit val type1Parser:JsonParserLike[Type1] = new JsonParserLike[Type1] {
override def parse(payload: String): Try[Type1] = Success(Type1("type1"))
}
implicit val type2Parser:JsonParserLike[Type2] = new JsonParserLike[Type2] {
override def parse(payload: String): Try[Type2] = Success(Type2("type2"))
}
}
// Exiting paste mode, now interpreting.
import scala.util.{Failure, Success, Try}
defined trait JsonParserLike
defined object JsonParserLike
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait Parser {
def parse[T](payload : String) : Try[T]
}
class JsonParser extends Parser {
override def parse[T](payload: String): Try[T] = parseInternal(payload)
private def parseInternal[T:JsonParserLike](payload:String):Try[T] = {
implicitly[JsonParserLike[T]].parse(payload)
}
}
// Exiting paste mode, now interpreting.
<pastie>:24: error: ambiguous implicit values:
both value type1Parser in object JsonParserLike of type => JsonParserLike[Type1]
and value type2Parser in object JsonParserLike of type => JsonParserLike[Type2]
match expected type JsonParserLike[T]
override def parse[T](payload: String): Try[T] = parseInternal(payload)
As I've already tried to explain in the comments, the problem is that the method
override def parse[T](payload: String): Try[T] = parseInternal(payload)
does not accept any JsonParserLike[T] instances. Therefore, the compiler has no way to insert the right instance of JsonParserLike[T] at the call site (where the type T is known).
To make it work, one would have to add some kind of token that uniquely identifies type T to the argument list of parse. One crude way would be to add a JsonParserLike[T] itself:
import util.Try
trait Parser {
def parse[T: JsonParserLike](payload : String) : Try[T]
}
class JsonParser extends Parser {
override def parse[T: JsonParserLike](payload: String): Try[T] =
parseInternal(payload)
private def parseInternal[T:JsonParserLike](payload:String):Try[T] = {
implicitly[JsonParserLike[T]].parse(payload)
}
}
trait JsonParserLike[T] {
def parse(payload: String): Try[T]
}
object JsonParserLike {
implicit val type1Parser: JsonParserLike[String] = ???
implicit val type2Parser: JsonParserLike[Int] = ???
}
Now it compiles, because the JsonParserLike[T] required by parseInternal is inserted automatically as an implicit parameter to parse.
This might be not exactly what you want, because it creates a hard dependency between Parser interface and the JsonParserLike typeclass. You might want to get some inspiration from something like shapeless.Typeable to get rid of the JsonParserLike in the Parser interface, or just rely on circe right away.
It seems like there is an extra complexity from a mix of different types of polymorphism in both examples. Here is a minimal example of just a type class:
// type class itself
trait JsonParser[T] {
def parse(payload: String): Try[T]
}
// type class instances
object JsonParserInstances {
implicit val type1Parser: JsonParser[Type1] = new JsonParser[Type1] {
def parse(payload: String): Try[Type1] = ???
}
implicit val type2Parser: JsonParser[Type2] = new JsonParser[Type2] {
def parse(payload: String): Try[Type2] = ???
}
}
// type class interface
object JsonInterface {
def parse[T](payload: String)(implicit T: JsonParser[T]): Try[T] = {
T.parse(payload)
}
}
def main(args: Array[String]): Unit = {
import JsonParserInstances._
JsonInterface.parse[Type1]("3")
JsonInterface.parse[Type2]("3")
}
More info:
Chapter on Typeclasses in free Scala with Cats Book
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)
}