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.)
Related
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.
What difference does the compiler see in BroFinder1 and BroFinder2 that causes the first one to fail? I really need BroFinder1 to work as it is without utilizing patterns such as Aux Pattern.
trait Brother[I] {
type Bro
def get: Bro
}
class Foo
object Foo {
implicit object bro extends Brother[Foo] {
override type Bro = Bar
override def get = new Bar
}
}
class Bar {
def barSpecificAction(): Unit = ()
}
class BroFinder1[I](implicit val b: Brother[I]) {
def brotherOf: b.Bro = b.get
}
class BroFinder2[I] {
def brotherOf(implicit b: Brother[I]): b.Bro = b.get
}
new BroFinder1[Foo].brotherOf.barSpecificAction() // Doesn't compile
//error: Error:(73, 32) value barSpecificAction is not a member of _1.b.Bro
//new BroFinder1[Foo].brotherOf.barSpecificAction();
^
new BroFinder2[Foo].brotherOf.barSpecificAction() // Ok
//scala version: 2.12.4
This is not a perfect answer but probably will provide some insights. The issue seems to be not related to implicit at all. It seems to be related to another fairly advance Scala feature: path-dependent types. Particularly the trouble seems to come from the fact that Scala type system is not powerful enough to express type difference between finder1 and finder2 precisely in following code:
object Foo {
implicit object bro extends Brother[Foo] {
override type Bro = Bar
override def get = new Bar
}
object bro2 extends Brother[Foo] {
override type Bro = Foo
override def get = new Foo
}
}
val finder1 = new BroFinder1[Foo]
val finder2 = new BroFinder1[Foo]()(Foo.bro2)
val bof1 = finder1.brotherOf
val bof2 = finder2.brotherOf
Sidenote: the fact that some parameter is implicit doesn't make it a "constant" because you can always pass the parameter explicitly anyway or you can have different visible implicit values in different contexts.
AFAIU the most precis type the finder1 or finder2 might be assigned in this example is just BroFinder1[Foo]. Particularly there is no way to catch different values of the b implicit variable and thus there is no way to pass further exactly the value of the path-dependent type that is encoded inside that value. Thus the best compiler knows about the types of bof1 and bof2 is that they both have type in form of _1.b.Bro where _1 means some particular instance of BroFinder1[Foo]. And so the compiler can't be sure that bof1 is actually of type Bar while bof2 is of type Foo.
The second example works because implicit parameter is captured in the same context so compiler knows exactly what the result type of brotherOf is.
The only workaround I know is not exactly suitable in your case: use "Aux" type. If your BroFinder took also an explicit parameter of type Foo, the solution might have looked like this:
type BrotherAux[I, B] = Brother[I] {type Bro = B}
class BroFinder3[I, B](val v: I)(implicit val b: BrotherAux[I, B]) {
def brotherOf: B = b.get
}
new BroFinder3(new Foo).brotherOf.barSpecificAction()
But in your case it has to be much less helpful
class BroFinder1[I, B](implicit val b: BrotherAux[I, B]) {
def brotherOf: B = b.get
}
new BroFinder1[Foo, Bar].brotherOf.barSpecificAction()
Because new BroFinder2[Foo].brotherOf is of type Bar and Bar has method barSpecificAction but new BroFinder1[Foo].brotherOf is of existential type
x.Bro forSome { val x: Brother[Foo] }
and it doesn't have method barSpecificAction.
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.
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.
I have a class that takes an implicit parameter which is used by functions called inside class methods. I want to be able to either override that implicit parameter, or alternatively, have the implicit argument be copied from its source. As an example:
def someMethod()(implicit p: List[Int]) {
// uses p
}
class A()(implicit x: List[Int]) {
implicit val other = List(3) // doesn't compile
def go() { // don't want to put implicit inside here since subclasses that override go() have to duplicate that
someMethod()
}
}
The behavior I want is that someMethod() gets an implicit parameter that is some changed version of x, which was the class's implicit parameter. I want to be able to either mutate x without changing it for whatever passed it into A's constructor, or otherwise override it to a new value of my choosing. Both approaches don't seem to work. That is, it doesn't copy the list in the former case, and the compiler finds an ambiguous implicit value for the latter case. Is there a way to do this?
I realize that I can redefine the implicit value within go(), but this is not a good choice in my case because this class is subclassed numerous times, and I'd like to handle this implicit change in the base class only. So it doesn't necessarily need to go in the constructor, but it must be in a method other than go().
Introduce another wrapper type, simply to disambiguate:
// badly named, choose something domain-specific
case class ListHolder(theList: List[Int])
def someMethod()(implicit holder: ListHolder) {
val xs = holder.theList
// uses xs ...
}
class A()(implicit xs: List[Int]) {
implicit val other = ListHolder(42 :: xs) // compiles
def go() {
// xs is never considered for the implicit param to someMethod()
// because it's now the wrong type
}
}
This also makes the code more self-documenting, as it becomes blindingly obvious that the two implicits are not one and the same.
If you want to have zillions of implicits floating around that don't collide with each other, you can create a wrapper class that you can tag with marker traits for implicit usage. There are a variety of syntaxes you could use; here's one example:
object Example {
class Implication[A,B](val value: A) {
def apply[C](c: C) = new Implication[C,B](c)
}
object Implication {
def mark[B] = new Implication[Unit,B](())
implicit def implication_to_value[A,B](i: Implication[A,B]) = i.value
}
trait One {}
trait Two {}
implicit val x = Implication.mark[One]("Hello")
implicit val y = Implication.mark[Two]("Hi")
def testOne(implicit s: Implication[String,One]) = println(s: String)
def testTwo(implicit s: Implication[String,Two]) = println(s: String)
def testThree(s: String) = println("String is " + s)
def main(args: Array[String]) {
testOne
testTwo
testThree(x)
testThree(y)
}
}
Which works as you would hope:
scala> Example.main(Array())
Hello
Hi
String is Hello
String is Hi
Since you have to use a wrapper object, it's not super-efficient, but it can be very effective. (Or very confusing, given how much happens implicitly.)
This modification compiles. I changed x into a var:
class A()(implicit var x: List[Int]) {
def someMethod()(implicit p: List[Int]) {
// uses p
}
x = List(3)
def go() { // don't want to put implicit inside here since subclasses that override go() have to duplicate that
someMethod()
}
}