Scala method Inferred generic type - scala

So I have this simple Scala trait with a method that requires a type parameter specified.
The DAO class extends the trait and uses the trait's method. Even if I do not provide a concrete type to the method, the code still compiles, and I suppose this is achieved by Scala auto inferring the generic type (guessing what the type value should be)? Is it right?
And also how does Scala infer types in situations like this in general?
Thanks a lot!!
class DAO #Inject()(val configProvider: DatabaseConfigProvider) extends
ManagementAppDatabase {
private val users = TableQuery[UserTable]
def findUserByEmail(email: String): Future[Option[User]] = {
execute(users.filter(_.email === email).result.headOption)
}
}
trait ManagementAppDatabase {
val configProvider: DatabaseConfigProvider
def execute[T](dBIO:DBIO[T]): Future[T] = configProvider.get[JdbcProfile].db.run(dBIO)
}

It's not a guess, the compiler can infer the type in this case as the object passed to the method has the type defined:
def execute[T](dBIO:DBIO[T]): Future[T] = configProvider.get[JdbcProfile].db.run(dBIO)
So if you pass a type DBIO[Int], the compiler can fill in the rest:
def execute[Int](dBIO:DBIO[Int]): Future[Int] = configProvider.get[JdbcProfile].db.run(dBIO)

Related

Scala type classes with constructor dependency injection

I'm trying to figure out how to get traditional constructor-based dependency injection to work with type class patterns.
For example, given
trait MyTypeClass[A] {
def doSomething(a: A): Unit
}
class TypeClasses(prefix: String) {
implicit val stringTC = new MyTypeClass[String] {
def doSomething(a: String) = println(s"$prefix a")
}
implicit val intTc = new MyTypeClass[Int] {
def doSomething(a: Int) = println(s"s$prefix $a")
}
}
class MyLogic {
def doSomething[A](a: A)(implicit myTypeClass: MyTypeClass[A]) = myTypeClass.doSomething(a)
doSomething("Hello world")
}
What would be the best way to get the implicit type class instances inside an instance of TypeClasses into MyLogic?
The only things I've come up with are to either
a) Inject an instance of TypeClasses into MyLogic in the constructor, and then import instanceOfTypeClasses._. However this has the downside that it has to be repeated every class, and subclasses can't inherit the import.
or b) make TypeClasses a trait, prefix a def, and have MyLogic extend TypeClasses and then dependency inject an instance for prefix in the constructor. However this becomes messy as it's allowing the dependencies for TypeClasses to bleed into MyLogic.
In case you need dependency injection, as I may assume from your tags, you may try to use distage (slides) DI framework for Scala (disclaimer: I'm the author).
It supports typeclass instance injection.
Because your typeclass instances are created dynamically in the TypeClasses class,
you have to add a TypeClasses constructor parameter in every class that needs
to call a function that requires a typeclass instance.
But, you can remove the import typeclasses._ boilerplate by creating implicit
defs that would extract the instances from the TypeClasses object when it's available as an implicit:
trait MyTypeClass[A] {
def doSomething(a: A): Unit
}
object MyTypeClass {
implicit def intFromTypeClasses(implicit typeClasses: TypeClasses): MyTypeClass[Int] = typeClasses.intTc
implicit def stringFromTypeClasses(implicit typeClasses: TypeClasses): MyTypeClass[String] = typeClasses.stringTC
}
Because the implicit defs are defined in the companion object for MyTypeClass they will always be available without any imports.
Then you should add TypeClasses as an implicit parameter in MyLogic, this would make it available for implicit defs to extract instances from:
class MyLogic(implicit typeClasses: TypeClasses) {
def doSomething[A](a: A)(implicit myTypeClass: MyTypeClass[A]) = myTypeClass.doSomething(a)
doSomething("Hello world")
// same as doSomething("Hello world")(MyTypeClass.stringFromTypeClasses(typeClasses))
}
Then, in distage, declare the following bindings
import distage._
class MyAppModule extends ModuleDef {
make[String].from("myprefix")
make[TypeClasses]
make[MyLogic]
}
And everything is wired:
val ctx: Locator = Injector().produce(new MyAppModule)
implicit val typeClasses = ctx.get[TypeClasses]
ctx.get[MyLogic].doSomething("Hello world")

How to reflectively parameterise a generic type in Scala?

How can I implement the following psuedocode in Scala using reflection?
I require this for the purposes of looking-up a generic type from Guice:
trait Foo[A]
class FooInt extends Foo[Int]
class FooString extends Foo[String]
bind(new TypeLiteral<Foo<Int>>() {}).to(FooInt.class);
def fooTypeLiteral(paramA: Class[_]): TypeLiteral[_] = ???
val foo = injector.getInstance(fooTypeLiteral(classOf[Int])
// foo: FooInt
Note: I do not have access to the type of A at compile time, hence the _. The entire solution needs to be performed reflectively (e.g. I cannot have parameterizeFoo[A : ClassTag](...)).
You could try to create a ParameterizedType and pass it to the factory method of the TypeLiteral:
def fooTypeLiteral(paramA: Class[_]): TypeLiteral[_] = {
TypeLiteral.get(new java.lang.reflect.ParameterizedType() {
def getRawType = classOf[Foo[_]]
def getOwnerType = null
def getActualTypeArguments = Array(paramA)
})
}
If you have only a finite number of Foo implementations, you could try this:
trait Foo[A]
class FooInt extends Foo[Int]
class FooString extends Foo[String]
val TLFI = new TypeLiteral[Foo[Int]](){}
val TLFS = new TypeLiteral[Foo[String]](){}
bind(TLFI).to(FooInt.class);
bind(TLFS).to(FooString.class);
def fooTypeLiteral(c: Class[_]): TypeLiteral[_] = {
if (c == classOf[Int]) TLFI
else if (c == classOf[String]) TLFS
else throw new Error
}
Both Scala and Java compilers implement generics with type erasure. This means that all type information for sub-types of generics is lost when the source code is converted to JVM byte code. If the generic class itself does not hold ClassTag or similar, embedded information, then you cannot get the class at run time.

Slick Scala method inferred generic type

So I wanted to implement a trait to have a common execute function to run slick's query.
As you can see from the code below, I have one trait that has a type parameter on the class and the other define the type parameter on the method.
When I compile, the trait with method generic type compiles(without giving any type argument) but the other one does not.
Why??? I tried to give the class type arguments UserTable or User (my slick table def and projected case class) but none of them works. The error just says "expects DBIO[UserTable] but actual MySQLDriver.StreamingDriverAction"
Any help really appreciated.
Thanks a lot!!!
class DAO #Inject()(val configProvider: DatabaseConfigProvider) extends
ManagementAppDatabase {
private val users = TableQuery[UserTable]
def findUserByEmail(email: String): Future[Option[User]] = {
execute(users.filter(_.email === email).result.headOption)
}
}
trait ManagementAppDatabase {
val configProvider: DatabaseConfigProvider
def execute[T](dBIO:DBIO[T]): Future[T] = configProvider.get[JdbcProfile].db.run(dBIO)
}
trait ManagementAppDatabase[T] {
val configProvider: DatabaseConfigProvider
def execute (dBIO:DBIO[T]):Future[T]=configProvider.get[JdbcProfile].db.run(dBIO)
}
If you extend e.g. ManagementAppDatabase[User], then you can only call execute on DBIO[User]. But users.filter(_.email === email).result.headOption is DBIO[Option[User]]. That's it.

Overriding issues in Scala

I will let the code speak:
import scala.concurrent.Future
trait SomeRequest
trait SomeResponse
trait ApiStandard {
def apiCall[Req <: SomeRequest, Resp <: SomeResponse](request: Req): Future[Resp]
}
case class XXRequest() extends SomeRequest
case class XXResponse() extends SomeResponse
class XXStandard extends ApiStandard {
override def apiCall(request: XXRequest): Future[XXResponse] = ???
}
Basically I have a couple of data traits (SomeRequest, SomeResponse) and a behaviour trait ApiStandard. There are also case classes XXRequest and XXResponse which override the data traits. I am trying to create a concrete implementation of of ApiStandard called XXStandard. But it's not syntactically correct. Being a Scala beginner, I can't understand why.
Please throw some light.
Thanks.
ApiStandard defines a method apiCall that accepts a parameter that is more flexible than what XXStandard provides.
To illustrate,
If you have
val something: ApiStandard = ???
you know you can call
val req: SomeRequest
something(req)
If the ??? would be able to be new XXStandard(), and XXStandard only accepts XXRequests as it's argument to apiCall, this would be broken: there is no way to know req is in fact an XXRequest, and indeed, it doesn't have to be one.
Furtunately, this doesn't compile, because apiCall in XXStandard can't implement ApiStandard.apiCall.
To make XXStandard into something that can be a subtype of ApiStandard, apiCall in XXStandard has to take a type that is what you declared in your trait, or a supertype of that as its argument.
tl;dr:
Methods are contravariant in their parameter type.
Your definition of apiCall says it must work for any Req <: SomeRequest and Resp <: SomeResponse, so the caller can call it like (e.g.) apiCall[MyReq, SomeoneElsesResp](new MyReq). But the implementation in XXStandard doesn't work like this; it only supports a single request and response type. Assuming that's what you wanted, you need to move type arguments to ApiStandard:
trait ApiStandard[Req <: SomeRequest, Resp <: SomeResponse] {
def apiCall(request: Req): Future[Resp]
}
class XXStandard extends ApiStandard[XXRequest, XXResponse] {
override def apiCall(request: XXRequest): Future[XXResponse] = ???
}

Scala reflection to instantiate scala.slick.lifted.TableQuery

I have this base trait
trait MyBase {
type M
type T <: Table[M]
val query: TableQuery[T]
}
Where TableQuery is scala.slick.lifted.TableQuery
My subclasses instantiate TableQuery like so:
type M = Account
type T = AccountsTable
val query = TableQuery[T]
I'd like to instantiate the TableQuery in the base trait, possibly by using a lazy val, i.e.
lazy val query: TableQuery[T] = {
...
}
I've been playing around with reflection, but haven't had much luck.
If I understand correctly, what you want is to be able to extend
MyBase by simply defining M and T but without having to explicitly instantiate the TableQuery in each derived class.
Using reflection is not really an option because normally you use TableQuery.apply
for that (as in val query = TableQuery[MyTable]), and this is implemented through a macro,
so you've got a "runtime vs compile-time" issue.
If you absolutely need MyBase to be a trait (as opposed to a class), then I don't see any viable solution.
However if you can turn MyBase into a class and turn M and T into type parameters (instead of abstract types), then there is at least one solution.
As I hinted in another related question (How to define generic type in Scala?), you can
define a type class (say TableQueryBuilder) to capture the call to TableQuery.apply (at the point where the concrete type is known) along with an implicit macro (say TableQueryBuilder.builderForTable) to provide
an instance of this type class. You can then define a method (say TableQueryBuilder.build) to actually instantiate the TableQuery, which will just delegate to job to the type class.
// NOTE: tested with scala 2.11.0 & slick 3.0.0
import scala.reflect.macros.Context
import scala.language.experimental.macros
object TableQueryBuilderMacro {
def createBuilderImpl[T<:AbstractTable[_]:c.WeakTypeTag](c: Context) = {
import c.universe._
val T = weakTypeOf[T]
q"""new TableQueryBuilder[$T]{
def apply(): TableQuery[$T] = {
TableQuery[$T]
}
}"""
}
}
trait TableQueryBuilder[T<:AbstractTable[_]] {
def apply(): TableQuery[T]
}
object TableQueryBuilder {
implicit def builderForTable[T<:AbstractTable[_]]: TableQueryBuilder[T] = macro TableQueryBuilderMacro.createBuilderImpl[T]
def build[T<:AbstractTable[_]:TableQueryBuilder](): TableQuery[T] = implicitly[TableQueryBuilder[T]].apply()
}
The net effect is that you don't need anymore to know the concrete value of the type T in order to be able to instantiate a TableQuery[T],
provided that you have an implicit instance of TableQueryBuilder[T] in scope. In other words, you can shift the need to know the concrete value of T
up to the point where you actually know it.
MyBase (now a class) can then be implemented like this:
class MyBase[M, T <: Table[M] : TableQueryBuilder] {
lazy val query: TableQuery[T] = TableQueryBuilder.build[T]
}
And you can then extend it without the need to explcitly call TableQuery.apply:
class Coffees(tag: Tag) extends Table[(String, Double)](tag, "COFFEES") {
def name = column[String]("COF_NAME")
def price = column[Double]("PRICE")
def * = (name, price)
}
class Derived extends MyBase[(String, Double), Coffees] // That's it!
What happens here is that in Derived's constructor, an implicit value for TableQueryBuilder[Coffees] is implicitly
passed to MyBase's constructor.
The reason why you cannot apply this pattern if MyBase were a trait is pretty mundane: trait constructors cannot have parameters, let alone implicit parameters, so there would be no implicit way
to pass the TableQueryBuilder instance.