Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using Any for Union type a good idea?

Tags:

scala

I want to create a class generator (for Avro models). I have a problem because sometime the field of the class I generate could be one of many different types, let's say it could be an Int or a String or whatever. The simple idea is to create that field with the type Any and check at runtime that it is ok.

The problem is that using Any discard some of the powerfull features of the scala type system. Some bug in the code will not be caught at compile time (if I give a List to a function expecting a String or Int covered by an Any).

For example :

Let's I have this description of my class :

{"className" : "MyClass", "fields" : [
  { "fieldName" : "myField", "type" : ["String", "Int"]}
]}

From this description, I create this class :

class MyClass(myField: Any)

I want to create something like this :

class MyClass(myField: String or Int)

Should I stop using Any ? Is using Any generally considered a good idea in the scala community ?

like image 623
Moebius Avatar asked Jul 30 '16 20:07

Moebius


People also ask

What is Union in typing?

typing. Union. Union type; Union[X, Y] is equivalent to X | Y and means either X or Y. To define a union, use e.g. Union[int, str] or the shorthand int | str .

Why union types?

Union types are used when a value can be more than a single type. Such as when a property would be string or number .

How check string is member of union type?

To check if a string is in a union type:Create a reusable function that takes a string as a parameter. Add the values of the union type of an array. Use the includes() method to check if the string is contained in the array.

What is a union TypeScript?

In TypeScript, we can define a variable which can have multiple types of values. In other words, TypeScript can combine one or two different types of data (i.e., number, string, etc.) in a single type, which is called a union type.


1 Answers

Is using Any generally considered a good idea in the scala community?

Nope. Any means no type information, so it's generally considered a bad practice.

In Scala you can express a union type using Either, although it gets cumbersome if you have a lot of possible types in the union. Example:

class MyClass(myField: Either[String, Int]) {
  def doSomething = myField match {
    case Left(myStringField) => ???
    case Right(myIntField) => ???
  }
}

Another viable approach would be to make MyClass generic in its type:

class MyClass[A](myField: A)

However this is not setting any constraint on the type of A.

In order to place a constraint, e.g. make it a finite subset of types, you can use ad-hoc polymorphism:

trait MyConstraint[A]
class MyClass[A: MyConstraint](myField: A)

Now new MyClass(myValue) won't compile unless there is an implicit MyConstraint[A] in scope. Now you can whitelist the types you want to allow using implicit values

implicit object IntConstraint extends MyConstraint[Int]
implicit object StringConstraint extends MyConstraint[String]

Example:

new MyClass(42) // ok, there's implicit evidence of MyConstraint[Int]
new MyClass("foo") // ok, there's implicit evidence of MyConstraint[String]
new MyClass(false) // won't compile, no implicit evidence of MyConstraint[Boolean]

In technical terms, MyConstraint is a type class, used to refine the type A in the constructor of MyClass.

You can characterize a type class even further, by requiring that a set of operations are defined for each of its instances. E.g.

trait MyConstraint[A] {
  def mandatoryOp: A
}

implicit object IntConstraint extends MyConstraint[Int] {
  def mandatoryOp = 42
}

implicit object StringConstraint extends MyConstraint[String] {
  def mandatoryOp = "foo"
}

class MyClass[A](myField: A)(implicit ev: MyConstraint[A]) {
  def doSomething: A = ev.mandatoryOp 
}

Please note that A: MyConstraint is just syntactic sugar for requiring an implicit parameter of type MyConstraint[A]. In the last example I chose the explicit syntax in order to have the implicit parameter ev available in scope.

like image 52
Gabriele Petronella Avatar answered Oct 19 '22 08:10

Gabriele Petronella