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.
Related
I'm using two Scala libraries that both rely on implicit parameters to supply codecs/marshallers for case classes (the libraries in question are msgpack4s and op-rabbit). A simplified example follows:
sealed abstract trait Event
case class SomeEvent(msg: String) extends Event
case class OtherEvent(code: String) extends Event
// Assume library1 needs Show and library2 needs Printer
trait Show[A] { def show(a: A): String }
trait Printer[A] { def printIt(a: A): Unit }
object ShowInstances {
implicit val showSomeEvent = new Show[SomeEvent] {
override def show(a: SomeEvent) =
s"SomeEvent: ${a.msg}"
}
implicit val showOtherEvent = new Show[OtherEvent] {
override def show(a: OtherEvent) =
s"OtherEvent: ${a.code}"
}
}
The Printer for the one library can be generic provided there's an implicit Show for the other library available:
object PrinterInstances {
implicit def somePrinter[A: Show]: Printer[A] = new Printer[A] {
override def printIt(a: A): Unit =
println(implicitly[Show[A]].show(a))
}
}
I want to provide an API that abstracts over the details of the underlying libraries - callers should only need to pass the case class, internally to the API implementation the relevant implicits should be summoned.
object EventHandler {
private def printEvent[A <: Event](a: A)(implicit printer: Printer[A]): Unit = {
print("Handling event: ")
printer.printIt(a)
}
def handle(a: Event): Unit = {
import ShowInstances._
import PrinterInstances._
// I'd like to do this:
//EventHandler.printEvent(a)
// but I have to do this
a match {
case s: SomeEvent => EventHandler.printEvent(s)
case o: OtherEvent => EventHandler.printEvent(o)
}
}
}
The comments in EventHandler.handle() method indicate my issue - is there a way to have the compiler select the right implicits for me?.
I suspect the answer is no because at compile time the compiler doesn't know which subclass of Event handle() will receive, but I wanted to see if there's another way. In my actual code, I control & can change the PrinterInstances code, but I can't change the signature of the printEvent method (that's provided by one of the libraries)
*EDIT: I think this is the same as Provide implicits for all subtypes of sealed type. The answer there is nearly 2 years old, I'm wondering if it's still the best approach?
You have to do the pattern matching somewhere. Do it in the Show instance:
implicit val showEvent = new Show[Event] {
def show(a: Event) = a match {
case SomeEvent(msg) => s"SomeEvent: $msg"
case OtherEvent(code) => s"OtherEvent: $code"
}
}
If you absolutely need individual instances for SomeEvent and OtherEvent, you can provide them in a different object so they can be imported separately.
If Show is defined to be contravariant (i.e. as trait Show[-A] { ... }, with a minus on the generic type) then everything works out of the box and a Show[Event] is usable as a Show[SomeEvent] (and as a Show[OtherEvent] for that matter).
If Show is unfortunately not written to be contravariant, then we might have to do a little bit more juggling on our end than we'd like. One thing we can do is declare all of our SomeEvent values as simply Events, vis a vis val fooEvent: Event = SomeEvent("foo"). Then fooEvent will be showable.
In a more extreme version of the above trick, we can actually hide our inheritance hierarchy:
sealed trait Event {
def fold[X]( withSomeEvent: String => X,
withOtherEvent: String => X ): X
}
object Event {
private case class SomeEvent(msg: String) extends Event {
def fold[X]( withSomeEvent: String => X,
withOtherEvent: String => X ): X = withSomeEvent(msg)
}
private case class OtherEvent(code: String) extends Event {
def fold[X]( withSomeEvent: String => X,
withOtherEvent: String => X ): X = withOtherEvent(code)
}
def someEvent(msg: String): Event = SomeEvent(msg)
def otherEvent(code: String): Event = OtherEvent(code)
}
Event.someEvent and Event.otherEvent allow us to construct values, and fold allows us to pattern match.
NOTE: if someone can come up with a better title for what I am trying to ask - please mention or edit.
Given a wrap method:
trait MyWrapperBound {
val message: String
}
def wrap[T <: MyWrapperBound](message: String): T
I am looking for a way to describe that all all implementations of MyWrapperBound should have a constructor that takes a message: String so I can construct and return it from my wrap method.
I can think of a couple of ways to do this:
Method 1 - using an implicit:
def wrap[T <: MyWrapperBound](message: String)(implicit factory: String => T): T
This would mean that any MyWrapperBound impl. would also have to create the implicit:
case class SimpleBound(message: String) extends MyWrapperBound
object SimpleBound {
implicit def factory(message: String): SimpleBound = SimpleBound(message)
}
This would result in a fair amount of boilerplate - which I'd like to avoid.
Method 2 - macro:
def wrap[T <: MyWrapperBound](message: String): T = macro ...
The macro would take the type, assert there is a valid constructor, constructing the type if its there and throw a nice compile error if not present for the developer to go and fix (by adding a valid constructor)
My question is - being fairly new to scala, is there a simpler option that I am missing? or another option that makes more sense?
If you're amenable to typeclasses there is a slightly simpler answer involving implicits. You can accomplish what you're trying to do rather easily by adding a type parameter to MyWrapperBound and enumerating the types of messages you'd like to support using the Show typeclass. For instance, if you knew everything that you were attempting to wrap supported a map A => String, you could supply a Show[A] implicit to your wrap method like so:
trait Show[A] {
def show(a: A): String
}
trait MyWrapperBound[A] {
val message: String
}
object MyWrapperBound {
def wrap[A](a: => A)(implicit ev: Show[A]): MyWrapperBound[A] =
new MyWrapperBound[A] {
override val message: String = ev.show(a)
}
}
object ShowInstances {
case class MyDS(someInformation: List[String])
implicit val simpleShow: Show[String] = new Show[String] {
override def show(a: String): String = a
}
implicit val slightlyMoreComplexShow: Show[MyDS] = new Show[MyDS] {
override def show(a: MyDS): String = a.someInformation.mkString("[", ",", "]")
}
}
As always, the code compiles and produces the desired output. Adding more support is as easy as adding more instances to ShowInstances. This allows you to decouple the map A => String from the wrapper logic itself, so that wrap becomes a simple constructor for MyWrapperBound.
If you don't like the idea of parametrizing your MyWrapperBound with a type parameter, it's not even necessary if you're not planning to have instances of it indexed by some message type.
I want to define a function with implicit parameter in a way like this:
// imports to add scope of A
{
implicit a: A => {
// some action
}
}.apply()
// somewhere in the code
class A
val a: A = new A
But my Scala compiler doesn't compile it. It says: Cannot resolve reference apply with such signature. However, the parameter is implicit, so I guess compiler should look up in the scope and find an appropriate object.
Is it true? If not, then how can I fix it?
You can't. Only methods can have implicit parameters.
When you do this:
// val f: A => Unit =
{
implicit a: A => {
// some action
}
}
you're actually declaring an anonymous function of type A => Unit and you are declaring the argument a as implicit in the function body
You can achieve something close to what you want using the magnet pattern:
class A
case class Magnet()
object Magnet {
implicit def fromUnit(arg1: Unit)(implicit a: A) = Magnet()
}
object Test extends App {
implicit val a = new A
{
args: Magnet => {
//...
}
}.apply()
}
You'll get a deprecation warning though because the magnet must have at least one parameter and I used Unit, you should call it like .apply(()) to avoid it
As said by Giovanni: You can't have such a parameter.
However you can use implicitly to resolve implicits within your function:
case class Foo(text : String)
implicit val foo = Foo("World")
(() => {
val implFoo : Foo = implicitly[Foo]
println(s"Hello ${implFoo.text}")
}).apply()
(But to be honest this sounds like it can be written better and you're going into spaghetti code territory with what you're doing.)
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.
I'm a bit new to Scala and I'm trying to write a generic client for a RESTful api I would like to use. I'm able to provide concrete Reads[T] and Writes[T] for the specific case classes I would like to instantiate my client for, however the compiler expects to find a Reads[T] and Writes[T] for any type, not just the types I'm using. Some code to illustrate (I've omitted irrelevant sections):
My generic client:
class RestModule[T](resource: String, config: Config) ... with JsonSupport{
...
def create(item: T): Future[T] = {
val appId = config.apiId
val path = f"/$apiVersion%s/applications/$appId%s/$resource"
Future {
val itemJson = Json.toJson(item)
itemJson.toString.getBytes
} flatMap {
post(path, _)
} flatMap { response =>
val status = response.status
val contentType = response.entity.contentType
status match {
case Created => contentType match {
case ContentTypes.`application/json` => {
Unmarshal(response.entity).to[T]
}
case _ => Future.failed(new IOException(f"Wrong Content Type: $contentType"))
}
case _ => Future.failed(new IOException(f"HTTP Error: $status"))
}
}
...
}
JsonSupprt Trait:
trait JsonSupport {
implicit val accountFormat = Json.format[Account]
}
I'm only ever instantiating as RestModule[Account]("accounts",config) but I get the error
Error:(36, 32) No Json serializer found for type T. Try to implement an implicit Writes or Format for this type.
val itemJson = Json.toJson(item)
^
Why does the compiler think it needs a Writes for type T when T can only ever be of type Account? Is there any way to work around this?
The reason why the compiler doesn't like what you're doing is to do with how implicit parameters are resolved and more crucially when they are resolved.
Consider the snippet,
Object MyFunc {
def test()(implicit s: String): String = s
}
The implicit parameter only gets resolved by the parameter when the function is called, and basically is expanded as,
MyFunc.test()(resolvedImplicit)
In your particular case you actually call the function requiring the implicit and hence it looks for an implicit of T at that point in time. Since it can't find one in scope it fails to compile.
In order to solve this issue, simply add the implicit parameter to the create method to tell the compiler to resolve it when you call create rather than toJson within create.
Furthermore we can use scala's implicit rules to get the behaviour that you want.
Let's take your trait Reads,
trait Reads[A] {
}
object MyFunc {
def create[A](a: A)(implicit reads: Reads[A]): Unit = ???
}
as we said befeore you can call it if the implicit is in scope. However, in this particular case where you have predefined reads we can actually put it in the companion object,
object Reads {
implicit val readsInt: Reads[Int] = ???
implicit val readsString: Reads[String] = ???
}
This way when create is called, the user doesn't need to import or define any implicit vals when A is Int or String because scala automatically looks in the companion object for any implicit definitions if it can't find one in the current scope.