scala implicit in function type definition - scala

I have following abstract class:
abstract class FieldProvider[+T: Writes](db: DB)(implicit i: RequestAction, j: ExecutionContext) {}
and following implementations:
class LengthProvider extends FieldProvider ...
object LengthProvider extends ((DB) => LengthProvider) {
def apply(v1: DB): LengthProvider = new LengthProvider(v1)
}
class WidthProvider extends FieldProvider ...
object WidthProvider extends ((DB) => WidthProvider) {
def apply(v1: DB): WidthProvider = new WidthProvider(v1)
}
The reason why I have these apply methods is because I need following configuration map:
val providers: Map[String, ((DB) => FieldProvider)] = Map(
"length" -> LengthProvider,
"width" -> WidthProvider
)
So that I can initialize the providers by the string containing their name:
providers("length")(db) // returns a new instance of LengthProvider
Now, my problem is that all these providers constructors require two implicit variables. But I don't know how to include it into the function definition (DB) => FieldProvider. So, essentially, the apply method signature should be something like (DB)(implicit RequestAction, ExecutionContext) => FieldProvider, but I don't know if there is a correct syntax for what I'm trying to do.
I could also give up and pass them explicitly:
object WidthProvider extends ((DB, RequestAction, ExecutionContext) => WidthProvider) {
def apply(v1: DB, v2: RequestAction, v3: ExecutionContext): WidthProvider = new WidthProvider(v1)(v2,v3)
}
But then I'll have to pass them explicitly elsewhere, instead of providers("length")(db), I'd have to write providers("length")(db, implicitly[RequestAction], implicitly[ExecutionContext]), which doesn't feel right.

Let's assume FieldProvider has 2 methods that need the implicits. The more convenient way to avoid duplication is to pass them as constructor level implicit arguments and then all the internal methods in FieldProvider can "share" them.
However, this won't help in your current class tree, so to fix this, instead of doing:
abstract class FieldProvider()(implicit param1: X1..) {
def test: T = param1.doSomething
}
Simply move the implicit to method level such that you can provide it at a time different than extending the constructor.
abstract class FieldProvider() {
def test()(implicit param1: X1): T = param1.doSomething
}

So, essentially, the apply method signature should be something like (DB)(implicit RequestAction, ExecutionContext) => FieldProvider, but I don't know if there is a correct syntax for what I'm trying to do.
Note that you might directly get (in a future Scala 2017 version) an implicit function type.
See pull request 1775, by Odersky himself.
Let’s massage the definition of f1 a bit by moving the last parameter section to the right of the equals sign:
def f1(x: Int) = { implicit thisTransaction: Transaction =>
thisTransaction.println(s"first step: $x")
f2(x + 1)
}
The right hand side of this new version of f1 is now an implicit function value.
What’s the type of this value?
Previously, it was Transaction => Int, that is, the knowledge that the function has an implicit parameter got lost in the type.
The main extension implemented by the pull request is to introduce implicit function types that mirror the implicit function values which we have already.
Concretely, the new type of f1 is:
implicit Transaction => Int
Just like the normal function type syntax A => B, desugars to scala.Function1[A, B], the implicit function type syntax implicit A => B desugars to scala.ImplicitFunction1[A, B].
The same holds at other function arities. With dotty’s pull request #1758 merged, there is no longer an upper limit of 22 for such functions.

Related

Managing trait instance consumers in a generic way

Let's imagine I have the following base trait and case classes
sealed trait BaseTrait
case class Foo(x: Integer = 1) extends BaseTrait
case class Bar(x: String = "abc") extends BaseTrait
I would like to create a generic interface for classes which can process BaseTrait instances, something like the following
class FooProcessor(val model: FooModel) extends BaseProcessor[Foo] {
val v: Option[Foo] = model.baseVar
}
class BarProcessor(val model: BarModel) extends BaseProcessor[Bar] {
val v: Option[Bar] = model.baseVar
}
For this I have the following traits
trait BaseModel[T <: BaseTrait] {
var baseVar: Option[T] = None
}
trait BaseProcessor[T <: BaseTrait] {
def model: BaseModel[T]
def process(x: T): Unit = model.baseVar = Option(x)
}
The model definitions are the following
class FooModel extends BaseModel[Foo]
class BarModel extends BaseModel[Bar]
Now lets imagine I have the following processors somewhere in my app
val fooProcessor = new FooProcessor(new FooModel)
val barProcessor = new BarProcessor(new BarModel)
I would like to handle them in a somewhat generic way, like this
def func[T <: BaseTrait](p: T) {
val c/*: BaseProcessor[_ >: Foo with Bar <: BaseTrait with Product with Serializable]*/ = p match {
case _: Foo => fooProcessor
case _: Bar => barProcessor
c.process(p)
}
The compiler is not really happy about the last line, it says
type mismatch;
found : T
required: _1
If I understand correctly this is basically the compiler trying to prevent barProcessor.process(Foo()) from happening. I've tried a couple of solutions to get around this and achieve the desired behavior:
the simplest way around this is calling the proper *Processor.process with the proper BaseTrait instance inside the match case, which seems to defy the whole point of handling them in a somewhat generic way
use an abstract type in the BaseModel and BaseProcessor, which one hand got rid of the somewhat unneeded type parameter in BaseModel but the compilers complaint is still valid and I was not able to figure out if it's possible to get that to work
get rid of the type parameter and contraint from the BaseModel, and just do a type cast in the processor to get the proper type, but the explicit type cast also isn't really what I was hoping for
Like so:
trait BaseModel {
var baseVar: Option[BaseTrait] = None
}
trait BaseProcessor[T <: BaseTrait] {
def model: BaseModel
def process(x: T): Unit = model.baseVar = Some(x)
def getBaseValue: T = model.baseVar.map(_.asInstanceOf[T])
}
I guess one could also somehow convince the compiler that the two types (T of the Processor and T of the func parameter p) are equivalent, but that also seems like an overkill (and I'm also not really sure how it can be done).
So my question is the following: is it possible to do what I'm trying to achieve here (managing processors in a uniform way + each processor knows their specific type of BaseTrait) in a somewhat easy fashion? Is there a better model for this which I'm missing?
Update
As per Tim's answer making the controllers implicit solves the problem, however if you want to have a class where you define your controllers + have 'func' on it's interface the compiler no longer seems to properly resolve the implicits. So if I try to do something like this
class ProcessorContainer {
implicit val fooProcessor = new FooProcessor(new FooModel)
implicit val barProcessor = new BarProcessor(new BarModel)
def func[T <: BaseTrait](p: T) = typedFunc(p)
private def typedFunc[T <: BaseTrait](p: T)(implicit processor: BaseProcessor[T]) =
processor.process(p)
}
class Test {
val processorContainer = new ProcessorContainer
processorContainer.func(Foo())
processorContainer.func(Bar())
}
I get the following compile error (one for Foo and one for Bar):
could not find implicit value for parameter processor: BaseProcessor[Foo]
not enough arguments for method
Is there a way around this? I could of course expose the controllers so they can be passed in implicitly, however I'd prefer not doing that.
You can create a simple typeclass by making the processors implicit and passing them as an extra argument to func:
implicit val fooProcessor = new FooProcessor(new FooModel)
implicit val barProcessor = new BarProcessor(new BarModel)
def func[T <: BaseTrait](p: T)(implicit processor: BaseProcessor[T]) =
processor.process(p)
If you pass a Foo to func it will call FooProcessor.process on it, and if you pass a Bar to func it will call BarProcessor on it.

Explain request passing in play framework

I was trying this in playframework. When I came through this part, at first it seemed pretty straightforward but while trying to trace it I'm not able to understand how this works. I know what kind of parameter is accepted by apply method of Action but I couldn't get how request is available and how it can be passed to Ok. Can anyone show analogous example with simple definition in scala.
#Singleton
class HomeController #Inject()(configuration: Configuration, cc: ControllerComponents)(implicit assetsFinder: AssetsFinder)
extends AbstractController(cc) {
def tweets = Action { implicit request =>
Ok(s"request is $request")
}
}
Thanks in advance
I'll try and simplify a bit:
trait A extends (String => String) { self => def apply() = this }
A effectively extends a function from String to String.
object A { def apply(f: String => String): A = new A { def apply(x: String) = f(x) } }
A's companion object actually implements A.
So you can now do this:
val f: String => String = _.toLowerCase
A(f)
This is valid Scala code.
You define f (toLowerCase on strings) and you pass it to the apply method of A.
This can also be written like this:
A { s => s.toLowerCase } // this way of putting it should remind you of Action { request => ... }
This is exactly how Play Action and EssentialAction works.
The other thing you ask is about Ok.
Ok is defined as a short version of Status with a set status code (200) and the given body (so something like Ok("Hello world!") will work.
On top of this there's the usual string interpolation you should know about.
Object Action extends trait DefaultActionBuilder extending trait ActionBuilder. The latter has method
apply(block: R[B] => Result): Action[B]
In your case request is of type Request[AnyContent] i.e. R is Request and B is AnyContent, Ok(s"request is $request") is of type Result,
Action { implicit request =>
Ok(s"request is $request")
}
is of type Action[B] i.e. Action[AnyContent]. So the syntax is just apply method of an object and a lambda as an argument of the method.
What is the apply function in Scala?
foo(implicit x => ???) is the same as foo(x => { implicit val x_ = x; ??? }).
Implicit keyword before a parameter in anonymous function in Scala
Ok is just new Status(OK) i.e. new Status(200) and class Status has method
def apply[C](content: C)(implicit writeable: Writeable[C]): Result
i.e. C is now String and content is s"request is $request" (i.e. string "request is " + request.toString).
If you use IDE you can investigate similar inheritance hierarchies and types yourself.

Provided implicit reader/writer for case class not found

I'm trying to write a nice generic persistence service with one implementation for mongo using Reactive Mongo and I'm struggling with providing the implicit reader/writer for my record class children. Here's the code.
First the base record class (each persisted record must implement it.
abstract class Record {
val _id: BSONObjectID = BSONObjectID.generate()
}
Second one record child case class (very simple) with its writer/reader (both possible way to do it, Macros vs custom in comment)
case class TestRecord() extends Record {}
object TestRecord {
// implicit object TestRecordWriter extends BSONDocumentWriter[TestRecord] {
// def write(testRecord: TestRecord): BSONDocument = BSONDocument()
// }
//
// implicit object TestRecordReader extends BSONDocumentReader[TestRecord] {
// def read(doc: BSONDocument): TestRecord = TestRecord()
// }
implicit def reader = Macros.reader[TestRecord]
implicit def writer = Macros.writer[TestRecord]
}
And then the service itself
class MongoPersistenceService[R <: Record] #Inject()()
(implicit ec: ExecutionContext, tag: ClassTag[R]) {
val collectionName: String = tag.runtimeClass.getSimpleName
def db: Future[DefaultDB] = MongoConnectionWrapper.getMongoConnection("mongodb://127.0.0.1", "27017")
.flatMap(_.database("testDb"))
def collection: Future[BSONCollection] = db.map(_.collection(collectionName))
def persist(record: R): Future[Unit] = {
collection.flatMap(_.insert(record)).map(_ => {})
}
def read(id: BSONObjectID): Future[R] = {
for {
coll <- collection
record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]
} yield record
}
}
And here's my failing test:
import scala.concurrent.ExecutionContext.Implicits.global
class MongoPersistenceServiceSpec extends WordSpec with Matchers with BeforeAndAfter {
val persistenceService = new MongoPersistenceService[TestRecord]()
"persist" when {
"called" should {
"succeeds when passing a not persisted record" in {
val testRecord = TestRecord()
persistenceService.persist(testRecord)
val persistedRecord = Await.result(persistenceService.read(testRecord._id), Duration(1000, "millis"))
assert(persistedRecord.eq(testRecord))
}
}
}
}
Compiler complains with following messages:
Error:(33, 32) could not find implicit value for parameter writer: reactivemongo.bson.BSONDocumentWriter[R]
collection.flatMap(_.insert(record)).map(_ => {})
Error:(33, 32) not enough arguments for method insert: (implicit writer: reactivemongo.bson.BSONDocumentWriter[R], implicit ec: scala.concurrent.ExecutionContext)scala.concurrent.Future[reactivemongo.api.commands.WriteResult].
Unspecified value parameters writer, ec.
collection.flatMap(_.insert(record)).map(_ => {})
Error:(39, 57) could not find implicit value for parameter reader: reactivemongo.bson.BSONDocumentReader[R]
record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]
Error:(39, 57) not enough arguments for method one: (implicit reader: reactivemongo.bson.BSONDocumentReader[R], implicit ec: scala.concurrent.ExecutionContext)scala.concurrent.Future[Option[R]].
Unspecified value parameters reader, ec.
record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]
Anybody has a idea what I might be missing?
I'm still new to scala so help me find the issue in here.
I already tried writing custom BSONWriter/BSONReader instead of the BSONDocumentWriter/BSONDocumentReader provided here without success.
In short, Scala doesn't search everywhere throughout your code for implicits. They need to be brought into scope, either through imports, passing them as parameters, or, as I would suggest here, through a context bound:
class MongoPersistenceService[R <: Record : BSONDocumentReader : BSONDocumentWriter]
This is a kind of short hand for (a) requiring that an implicit BSONDocumentReader[R] (and writer) can be found at the time that the class is constructed with a specific R, and (b) bringing those implicits into scope within the class's implementation so they can be implicitly passed to other methods like insert.
In order to fulfill that new requirement (a) you may have to import TestRecord._ within your test.
Your persist function doesn't have access to the fact that you have defined those implicit functions. The signature should be something like this:
def persist(record: R)(implicit def writer: BSONDocumentWriter[R]): Future[Unit]
And wherever you call persist and pass a TestRecord make sure that the implicit functions are in scope.

Is it possible to define a function return type based on a defined mapping from the type of a function argument?

Ideally I'd like to be able to do the following in Scala:
import Builders._
val myBuilder = builder[TypeToBuild] // Returns instance of TypeToBuildBuilder
val obj = myBuilder.methodOnTypeToBuildBuilder(...).build()
In principle the goal is simply to be able to 'map' TypeToBuild to TypeToBuildBuilder using external mapping definitions (i.e. assume no ability to change these classes) and leverage this in type inferencing.
I got the following working with AnyRef types:
import Builders._
val myBuilder = builder(TypeToBuild)
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[TypeToBuild.type, TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
Note that the type is passed as a function argument rather than a type argument.
I'd be supremely happy just to find out how to get the above working with Any types, rather than just AnyRef types. It seems this limitation comes since Singleton types are only supported for AnyRefs (i.e. my use of TypeToBuild.type).
That being said, an answer that solves the original 'ideal' scenario (using a type argument instead of a function argument) would be fantastic!
EDIT
A possible solution that requires classOf[_] (would really love not needing to use classOf!):
import Builders._
val myBuilder = builder(classOf[TypeToBuild])
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[classOf[TypeToBuild], TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
Being able to just use builder(TypeToBuild) is really just a win in elegance/brevity. Being able to use builder[TypeToBuild] would be cool as perhaps this could one day work (with type inference advancements in Scala):
val obj: TypeToBuild = builder.methodOnTypeToBuildBuilder(...).build();
Here is a complete, working example using classOf: http://ideone.com/94rat3
Yes, Scala supports return types based on the parameters types. An example of this would be methods in the collections API like map that use the CanBuildFrom typeclass to return the desired type.
I'm not sure what you are trying to do with your example code, but maybe you want something like:
trait Builder[-A, +B] {
def create(x: A): B
}
object Builders {
implicit val int2StringBuilder = new Builder[Int, String] {
def create(x: Int) = "a" * x
}
def buildFrom[A, B](x: A)(implicit ev: Builder[A, B]): B = ev.create(x)
}
import Builders._
buildFrom(5)
The magic with newInstance only works for concrete classes that have a constructor that takes no parameters, so it probably isn't generic enough to be useful.
If you're not afraid of implicit conversions, you could do something like this:
import scala.language.implicitConversions
trait BuilderMapping[TypeToBuild, BuilderType] {
def create: BuilderType
}
case class BuilderSpec[TypeToBuild]()
def builder[TypeToBuild] = BuilderSpec[TypeToBuild]
implicit def builderSpecToBuilder[TypeToBuild, BuilderType]
(spec: BuilderSpec[TypeToBuild])
(implicit ev: BuilderMapping[TypeToBuild, BuilderType]) = ev.create
case class Foo(count: Int)
case class FooBuilder() {
def translate(f: Foo) = "a" * f.count
}
implicit val FooToFooBuilder = new BuilderMapping[Foo, FooBuilder] {
def create = FooBuilder()
}
val b = builder[Foo]
println(b.translate(Foo(3)))
The implicit conversions aren't too bad, since they're constrained to these builder-oriented types. The conversion is needed to make b.translate valid.
It looked like wingedsubmariner's answer was most of what you wanted, but you didn't want to specify both TypeToBuild and BuilderType (and you didn't necessarily want to pass a value). To achieve that, we needed to break up that single generic signature into two parts, which is why the BuilderSpec type exists.
It might also be possible to use something like partial generic application (see the answers to a question that I asked earlier), though I can't put the pieces together in my head at the moment.
I'll resort to answering my own question since a Redditor ended up giving me the answer I was looking for and they appear to have chosen not to respond here.
trait Buildable[T] {
type Result
def newBuilder: Result
}
object Buildable {
implicit object ABuildable extends Buildable[A] {
type Result = ABuilder
override def newBuilder = new ABuilder
}
implicit object BBuildable extends Buildable[B] {
type Result = BBuilder
override def newBuilder = new BBuilder
}
}
def builder[T](implicit B: Buildable[T]): B.Result = B.newBuilder
class ABuilder {
def method1() = println("Call from ABuilder")
}
class BBuilder {
def method2() = println("Call from BBuilder")
}
Then you will get:
scala> builder[A].method1()
Call from ABuilder
scala> builder[B].method2()
Call from BBuilder
You can see the reddit post here: http://www.reddit.com/r/scala/comments/2542x8/is_it_possible_to_define_a_function_return_type/
And a full working version here: http://ideone.com/oPI7Az

Limitations of implicit resolution or type inference

I'm trying to understand why implicit resolution (or perhaps type inference) fails for the following Scala code. In this code, compilation fails on the second to last line, but succeeds on a modified version of the line where types are explicitly provided.
object O {
trait Wrapper[-A, +B] {
def func: A => B
}
object Identity
implicit class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
override def func: A => A = identity
}
// Compilation fails on the next line with error:
// found String("hello")
// required: A
Identity.func("hello")
// This line compiles.
implicitly[Identity.type => Wrapper[String, String]].apply(Identity).func("hello")
}
Travis Brown seems to be right, this is an occurence of the following: https://issues.scala-lang.org/browse/SI-6472
As a proof, I could make it compile using the work around given by Travis himself here: https://issues.scala-lang.org/browse/SI-6776
object O {
trait Wrapper[-A, +B] {
val funcFunc: A => B
def func( arg: A ): B = funcFunc( arg )
}
private class Private
trait BaseWrappable {
// Dummy method (cannot ever be called, just a work around to help the compiler)
def func( a: Private ) = ???
}
object Identity extends BaseWrappable
implicit class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
val funcFunc: A => A = identity
}
Identity.func("hello")
}
The code you have written is the same as:
class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
override def func: A => A = identity
}
implicit def identityToIdentityWrapper[A](self: Identity.type) = new Identity2Wrapper[A](self)
Note that the type parameter A is unbound until the the result from the call to func is used. The Scala compiler is not smart enough to look that far ahead and determine the type of A. Also, you cannot create a value of type [A] A => A in Scala. I'm actually surprised that the compiler doesn't infer A to be of type Nothing like it does when you call identityToIdentityWrapper explicitly.