How to test that an object is not a function in scala - function

My problem is quite simple : I want to have an implicit conversion of value to function if they are not already function. I plan to use a type safe pattern by requesting the instantiation of an implicit parameter (if the valueis a function the implicit creation fails).
However I do not see how to test that a value is not a function
I learned type safe pattern from user Beryllium in one of my previous question. See :
Type safe method chaining that doesn't allow repeats of operations
The implicit I've implemented is working, but too well. I want to transform not function expression to specific-application-default function automatically
implicit def defaultExecutionUnitParameterNReturn(a: Any): Unit => MyDefaultReturn =
{u : Unit => a }.andThen(_ => defaultReturn())
However my application would fail if the user implements "a" as a function
So my first idea was something like
implicit def defaultExecutionUnitParameterNReturn[A](a: A)(implicit e : A =!= Function) Unit => MyDefaultReturn =
{u : Unit => a }.andThen(_ => defaultReturn())
where implicit =!=[A,B] fails if A and B are the same type.
But "Function" does not exists

You need to place your implicit conversions in 2 traits
trait Implicits extends ImplicitsLow {
implicit def convertFunction[T, R](f: T => R) = ???
}
trait ImplicitsLow {
implicit def convert[T](t: T) = ???
}
Then you can observe that the function conversion is used in preference to the value one:
val result1: String = (i: Int) => i + 1
val result2: String = 1
// prints (function, value)
println((result1, result2))

Investigate below code snipped. This is standard implicit convertion example. toFunnction0 takes anything and converts it into Function0[R] or just simplified () => R.
implicit def toFunnction0[R](r: => R): Function0[R] = () => r
def iWantFunction0(f0: () => String) = {
f0()
}
def testFun = {println("computing string in testFun..."); "ABC"} //every time when called block of code will run
val abcVal = "ABC" //this is computed only once
iWantFunction0(testFun)
//here abcVal is not a function, so implicit works.
//toFunnction0 is in scope, so compiler will translate it into
//iWantFunction0(toFunnction0(abcVal))
iWantFunction0(abcVal)

Related

Null serialization in Scala Play (implicit Writes)

I'm experimenting with Scala Play and don't get why Null json Serialization doesn't work out of the box. I wrote a simple class to encapsulate data in response (ServiceResponse) which return a parametrical nullable field data and also made a Writes[Null] implicit, what am I missing? The compiler suggests to write a Writes[ServiceResponse[Null]] which works, but feels cumbersome and I wonder if there is a more concise way of solving the problem. Below is the code and error.
// <!-- EDIT -->
// The data I want to transfer
case class Person (name: String, age: Int)
object Person {
def apply(name: String, age: Int): Person = new Person(name, age)
implicit val reader: Reads[Person] = Json.reads[Person]
implicit val writer: OWrites[Person] = Json.writes[Person]
}
// <!-- END EDIT -->
case class ServiceResponse[T] (data: T, errorMessage: String, debugMessage: String)
object ServiceResponse {
def apply[T](data: T, errorMessage: String, debugMessage: String): ServiceResponse[T] =
new ServiceResponse(data, errorMessage, debugMessage)
implicit def NullWriter: Writes[Null] = (_: Null) => JsNull
implicit def writer[T](implicit fmt: Writes[T]) = Json.writes[ServiceResponse[T]]
}
// <!-- EDIT -->
// Given the above code I would expect
// the call ` Json.toJson(ServiceResponse(null, "Error in deserializing json", null))`
// to produce the following Json: `{ "data": null, "errorMessage": "Error in deserializing json", "debugMessage": null }`
No Json serializer found for type models.ServiceResponse[Null]. Try to implement an implicit Writes or Format for this type.
In C:\...\EchoController.scala:19
15 val wrapAndEcho = Action(parse.json) {
16 request =>
17 request.body.validate[Person] match {
18 case JsSuccess(p, _) => Ok(Json.toJson(echoService.wrapEcho(p)))
19 case JsError(errors) => BadRequest(Json.toJson(ServiceResponse(null,
20 "Error in deserializing json", null)))
21 }
22 }
EDIT
Tried to use Option instead (a more Scala-ish solution, indeed) but the structure of the code is the same and reports the same error
object ServiceResponse {
def apply[T](data: Option[T], errorMessage: Option[String], debugMessage: Option[String]): ServiceResponse[T] =
new ServiceResponse(data, errorMessage, debugMessage)
implicit def optionWriter[T](implicit fmt: Writes[T]) = new Writes[Option[T]] {
override def writes(o: Option[T]): JsValue = o match {
case Some(value) => fmt.writes(value)
case None => JsNull
}
}
implicit def writer[T](implicit fmt: Writes[Option[T]]) = Json.writes[ServiceResponse[T]]
}
I think I need some structural change, but I can't figure what. Also tried changing the type of fmt to Writes[T] (being T the only real variable type) and got a new Error.
diverging implicit expansion for type play.api.libs.json.Writes[T1]
[error] starting with object StringWrites in trait DefaultWrites
[error] case JsError(errors) => BadRequest(Json.toJson(ServiceResponse(None,
...
Thought I found a reasonable solution, but still getting error in the expansion of the implicit :( . I really need a hint.
object ServiceResponse {
def apply[T](data: Option[T], errorMessage: Option[String], debugMessage: Option[String]): ServiceResponse[T] =
new ServiceResponse(data, errorMessage, debugMessage)
implicit def writer[T](implicit fmt: Writes[T]): OWrites[ServiceResponse[T]] = (o: ServiceResponse[T]) => JsObject(
Seq(
("data", o.data.map(fmt.writes).getOrElse(JsNull)),
("errorMessage", o.errorMessage.map(JsString).getOrElse(JsNull)),
("debugMessage", o.debugMessage.map(JsString).getOrElse(JsNull))
)
)
}
NOTE
I think I got the problem. Since null is a possible value of an instance of Person I was expecting it to be handled by Writes[Person]. The fact is that Writes is defined as invariant in its type paramater (it's trait Writes[A] not trait Writes[+A]) so Writes[Null] does not match the definition of the implicit parameter as would happen if it was defined as Writes[+A] (Which in turns would be wrong violating Liskow substitution principle; it could have been Writes[-A], but this would have not solved the problem either, as we are trying to use the subtype Null of Person). Summing up: there is no shorter way to handle a ServiceResponse with a null data field than writing a specific implementation of Writes[ServiceResponse[Null]], which is neither a super nor a sub type of Write[ServiceResponse[Person]]. (An approach could be a union type, but I think it's an overkill). 90% sure of my reasoning, correct me if I'm wrong :)
To explain it better, the ServiceResponse case class takes a type parameter T, which can be anything. And play-json can only provide JSON formats for standard scala types, for custom types you need to define the JSON formatter.
import play.api.libs.json._
case class ServiceResponse[T](
data: T,
errorMessage: Option[String],
debugMessage: Option[String]
)
def format[T](implicit format: Format[T]) = Json.format[ServiceResponse[T]]
implicit val formatString = format[String]
val serviceResponseStr = ServiceResponse[String]("Hello", None, None)
val serviceResponseJsValue = Json.toJson(serviceResponseStr)
val fromString =
Json.fromJson[ServiceResponse[String]](serviceResponseJsValue)
serviceResponseJsValue
fromString
serviceResponseJsValue.toString
Json.parse(serviceResponseJsValue.toString).as[ServiceResponse[String]]
In the above example, you can see that I wanted to create a ServiceResponse with data being a string, so I implement a format string which's necessary for Json.toJson, as well as Json.fromJson to have the readers and writers implemented for the type T. Since T being String and is a standard type, play-json by default is resolving the same.
I have added the scastie snippet, which will help you understand the same better, and you can play around with the same.
<script src="https://scastie.scala-lang.org/shankarshastri/spqJ1FQLS7ym1vm1ugDFEA/8.js"></script>
The above explanation suffices a use-case wherein in case of None, the key won't even be present as part of the json, but the question clearly calls out for having key: null, in case if data is not found.
import play.api.libs.json._
implicit val config =
JsonConfiguration(optionHandlers = OptionHandlers.WritesNull)
case class ServiceResponse[T](
data: Option[T],
errorMessage: Option[String],
debugMessage: Option[String]
)
def format[T](implicit format: Format[T]) = Json.format[ServiceResponse[T]]
implicit val formatString = format[String]
val serviceResponseStr = ServiceResponse[String](None, None, None)
val serviceResponseJsValue = Json.toJson(serviceResponseStr)
val fromString =
Json.fromJson[ServiceResponse[String]](serviceResponseJsValue)
serviceResponseJsValue
fromString
serviceResponseJsValue.toString
Json.parse(serviceResponseJsValue.toString).as[ServiceResponse[String]]
Bringing the below line in the scope, will ensure to write nulls for optional.
implicit val config =
JsonConfiguration(optionHandlers = OptionHandlers.WritesNull)
<script src="https://scastie.scala-lang.org/shankarshastri/rCUmEqXLTeuGqRNG6PPLpQ/6.js"></script>

Scala, spray-json: universal enumeration json formatting

I have such model: two enumerations and one case class with two fields of these enums types:
// see later, why objects are implicit
implicit object Fruits extends Enumeration {
val Apple = Value("apple")
val Orange = Value("orange")
}
implicit object Vegetables extends Enumeration {
val Potato = Value("potato")
val Cucumber = Value("cucumber")
val Tomato = Value("tomato")
}
type Fruit = Fruits.Value
type Vegetable = Vegetables.Value
case class Pair(fruit: Fruit, vegetable: Vegetable)
I want to parse/generate JSONs to/from Pairs with spray-json. I don't want to declare separate JsonFormats for fruits and vegetables. So, I'd like to do something like this:
import spray.json._
import spray.json.DefaultJsonProtocol._
// enum is implicit here, that's why we needed implicit objects
implicit def enumFormat[A <: Enumeration](implicit enum: A): RootJsonFormat[enum.Value] =
new RootJsonFormat[enum.Value] {
def read(value: JsValue): enum.Value = value match {
case JsString(s) =>
enum.withName(s)
case x =>
deserializationError("Expected JsString, but got " + x)
}
def write(obj: enum.Value) = JsString(obj.toString)
}
// compilation error: couldn't find implicits for JF[Fruit] and JF[Vegetable]
implicit val pairFormat = jsonFormat2(Pair)
// expected value:
// spray.json.JsValue = {"fruit":"apple","vegetable":"potato"}
// but actually doesn't even compile
Pair(Fruits.Apple, Vegetables.Potato).toJson
Sadly, enumFormat doesn't produce implicit values for jsonFormat2. If I write manually two implicit declarations before pairFormat for fruits and vegetables formats, then json marshalling works:
implicit val fruitFormat: RootJsonFormat[Fruit] = enumFormat(Fruits)
implicit val vegetableFormat: RootJsonFormat[Vegetable] = enumFormat(Vegetables)
implicit val pairFormat = jsonFormat2(Pair)
// {"fruit":"apple","vegetable":"potato"}, as expected
Pair(Fruits.Apple, Vegetables.Potato).toJson
So, two questions:
How to get rid of these fruitFormat and vegetableFormat declarations?
Ideally it would be great to not make enumeration objects implicit, while keeping enumFormat function generic. Is there a way to achieve this? Maybe, using scala.reflect package or something like that.
You just have to replace enum.Value with A#Value.
Looking at spray-json #200 you can find an example of a well defined implicit enumFormat, slightly modified to leverage implicit enu retrieval:
implicit def enumFormat[T <: Enumeration](implicit enu: T): RootJsonFormat[T#Value] =
new RootJsonFormat[T#Value] {
def write(obj: T#Value): JsValue = JsString(obj.toString)
def read(json: JsValue): T#Value = {
json match {
case JsString(txt) => enu.withName(txt)
case somethingElse => throw DeserializationException(s"Expected a value from enum $enu instead of $somethingElse")
}
}
}
You can't, Scala doesn't allow implicit chaining, because it would lead to combinatorial explosions that would make the compiler too slow.
See https://docs.scala-lang.org/tutorials/FAQ/chaining-implicits.html
Scala does not allow two such implicit conversions taking place, however, so one cannot got from A to C using an implicit A to B and another implicit B to C.
You'll have to explicitly produce a JsonFormat[T] for each T you want to use.

Scala: Overloaded function with function as parameter

Given an overloaded function, with one taking a function as parameter. This parameter-function takes no arguments:
def func(param: () => Unit): Unit = {
param()
}
def func(param: Int): Unit = {
println(param)
}
While calling func with an anonymous function works perfect:
func(() => println("it works"))
Using a plain function fails:
def functionAsParam(): Unit = {
println("it works")
}
func(functionAsParam)
Obviously, Scala evaluates functionAsParam and don't pass the function itself to func. Question: How can I (as a user of a library which provides funcs) pass in a non-anonymous function?
There are several ways to do this. Either you explicitly pass the function as parameter:
scala> func(() => functionAsParam)
it works
scala> func (functionAsParam _ )
it works
(These two cases are slightly different though, in the sense that in the first example, you construct new anonymous function with your other function, and in the second example, you indicate that this function should not yet be evaluated, by adding _)
Or you create a variable which is a function and pass it along:
val fval = () => println("It works")
scala> func(fval)
It works
The error comes from the fact that you defined a method, but your func expects a function. Yeah, there is a problem with overloading in scala (in other areas as well). To fix it you need manually convert your method into a function (it's called eta-expantion):
func(functionAsParam _)
If you turn on -Xprint:typer you'll see that scalac expands you method into a function:
val res4: Unit = func({
(() => functionAsParam())
});

Scala type parameters by declaring the type inside the function

I'm just starting to learn Scala, coming from a Java background. I have been trying to understand type parameters in functions and inference of types. This is a standard example in the Scala docs:
class Decorator(left: String, right: String) {
def layout[A](x: A) = left + x.toString() + right
}
object FunTest extends Application {
def apply(f: Int => String, v: Int) = f(v)
val decorator = new Decorator("[", "]")
println(apply(decorator.layout, 7))
}
If I try to apply a type parameter to the apply function and keep v a strong type, a type mismatch occurs. Why doesn't the type get inferred here?
def apply[B](f: B => String, v: String) = f(v) //Type mismatch
def apply[B](f: B => String, v: B) = f(v) //Works fine
Thanks
Let's take a look at apply without it's body:
def apply[B](f: B => String, v: String)
That reads "apply is a function (method) parameterized on a type B, that takes a function from B to String, and a String".
Think of B as a type variable; it will need to be instantiated at some point. That point is not the declaration of apply. It is when apply is, well, applied to ;-)
By this contract, usage like this must be allowed:
def g(i: Int): String = "i is " + i
apply(g, "foo") // Here the type variable `B` is "instantiated" to the type Int,
But given that you have a body like f(v), just substituting, we see the contradiction:
Substitute
f(v)
With
g("foo") // can't compile; g takes a B, which is an Int

Two ways of defining functions in Scala. What is the difference?

Here is a little Scala session that defines and tries out some functions:
scala> def test1(str: String) = str + str;
test1: (str: String)java.lang.String
scala> test1("ab")
res0: java.lang.String = abab
works nicely.
scala> val test2 = test1
<console>:6: error: missing arguments for method test1 in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
val test2 = test1
^
oops.
scala> val test2 = test1 _
test2: (String) => java.lang.String = <function1>
scala> test2("ab")
res1: java.lang.String = abab
works well!
Now, I've seen the _ syntax when folding (_ + _, etc). So as I understand it _ basically means "an argument". So test1 _ basically means a function with an argument, which is given to test1". But why isn't that exactly the same as just test1? Why is there a difference if I append a _?
So I kept exploring...
scala> val test3 = (str: String) => str + str
test3: (String) => java.lang.String = <function1>
scala> test3("ab")
res2: java.lang.String = abab
scala> val test4 = test3
test4: (String) => java.lang.String = <function1>
Here it works without _! What's the difference between a defed function, and a valed function?
The def declares a method within a surrounding object/class/trait, similar to the way you define methods in Java. You can only use defs within other objects/classes/traits. In the REPL, you cannot see the surrounding object because it's "hidden", but it does exist.
You cannot assign a def to a value, because the def is not a value - it's a method in the object.
The (x: T) => x * x declares and instantiates a function object, which exists at runtime. Function objects are instances of anonymous classes which extend FunctionN traits. FunctionN traits come with an apply method. The name apply is special, because it can be omitted. Expression f(x) is desugared into f.apply(x).
The bottomline is - since function objects are runtime values which exist on the heap, you can assign them to values, variables and parameters, or return them from methods as return values.
To solve the issue of assigning methods to values (which can be useful), Scala allows you to use the placeholder character to create a function object from a method. Expression test1 _ in your example above actually creates a wrapper function around the method test1 - it is equivalent to x => test1(x).
There's no difference between a def'ed function and a val'ed function:
scala> def test1 = (str: String) => str + str
test1: (String) => java.lang.String
scala> val test2 = test1
test2: (String) => java.lang.String = <function1>
scala> val test3 = (str: String) => str + str
test3: (String) => java.lang.String = <function1>
scala> val test4 = test2
test4: (String) => java.lang.String = <function1>
See? All of these are functions, which is indicated by the X => Y type they have.
scala> def test5(str: String) = str + str
test5: (str: String)java.lang.String
Do you see an X => Y type? If you do, go see an ophthalmologist, because there's none. The type here is (X)Y, commonly used to denote a method.
Actually, test1, test2, test3 and test4 are all methods, which return functions. test5 is a method which returns a java.lang.String. Also, test1 through test4 do not take parameters (only test1 could, anyway), while test5 does.
So, the difference is pretty simple. In the first case, you tried to assign a method to a val, but did not fill in the parameters the method take. So it failed, until you added a trailing underscore, which meant turn my method into a function.
In the second example you had a function, so you didn't need to do anything else.
A method is not a function, and vice versa. A function is an object of one of the FunctionN classes. A method is a handle to some piece of code associated with an object.
See various questions about methods vs functions on Stack Overflow.
The underscore means different things in different contexts. But it can always be thought of as the thing that would go here, but doesn't need to be named.
When applied in place of parameters, the effect is to lift the method to a function.
scala> def test1(str: String) = str + str;
test1: (str: String)java.lang.String
scala> val f1 = test1 _
f1: (String) => java.lang.String = <function1>
Note, the method has become a function of type (String) => String.
The distinction between a method and a function in Scala is that methods are akin to traditional Java methods. You can't pass them around as values. However functions are values in their own right and can be used as input parameters and return values.
The lifting can go further:
scala> val f2 = f1 _
f2: () => (String) => java.lang.String = <function0>
Lifting this function results in another function. This time of type () => (String) => (String)
From what I can tell, this syntax is equivalent to substituting all of the parameters with an underscore explicitly. For example:
scala> def add(i: Int, j: Int) = i + j
add: (i: Int,j: Int)Int
scala> val addF = add(_, _)
addF: (Int, Int) => Int = <function2>
scala> val addF2 = add _
addF2: (Int, Int) => Int = <function2>