10

There is Either in scala which allow a variable to have 2 types value.

val x: Either[String, Int] = Left("apple")

However, I want to have more than 2 types for variable x e.g. {String, Int, Double, List[String] }.

e.g. val x:[type can be either String, Int, Double or List[String]]
//So that I can store either String, Int, Double, List[String] value in x.

Is there any way to achieve this?

4
  • I want to have more than 2 types for variable. Can you elaborate on what that actually means, perhaps by giving an example? Commented Apr 19, 2017 at 11:56
  • 1
    Either[Either[Either[String, Int], Double], List[String]] Commented Apr 19, 2017 at 11:58
  • @YuvalItzchakov I have updated the answer. Commented Apr 19, 2017 at 11:59
  • @JörgWMittag, is there any simpler way, because i realize that, I also have to provide Left/Right in nested way. e.g. for Int - Left(Left(Right(12))). Isn't there a way so that I can do like x = 12? Commented Apr 19, 2017 at 12:03

3 Answers 3

25

IMO the most natural way to express this is to create an ADT (Algebraic Data Type):

sealed trait Foo
final case class Bar(s: String) extends Foo
final case class Baz(i: Int) extends Foo
final case class Fizz(d: Double) extends Foo
final case class Buzz(l: List[String]) extends Foo

And now you can pattern match on Foo:

val f: Foo = ???
f match {
  case Bar(s) => // String
  case Baz(i) => // Int
  case Fizz(d) => // Double
  case Buzz(l) => // List[String]
}
Sign up to request clarification or add additional context in comments.

Comments

12

Look at shapeless coproducts

"shapeless has a Coproduct type, a generalization of Scala's Either to an arbitrary number of choices"

1 Comment

This seems to be the exactly what I wanted, however, I'll won't be able to use any external library right now but will consider this later. Btw, its very helpful to know about it. Thank you.
4

Not sure what your exact use case is but check this out: scala type alias - how to have a type that represent multiple data types

Basically you create a trait represents an umbrella/parent class. Then you define multiple classes that extend the parent trait and put the parent trait as the expected parameter type in your function. Then you can pass any type that extends that parent trait.

You have to wrap the subtypes, but this allows you to have one type that represents multiple types.

Another way could be to use generic types and type bounds. These articles talk about these two subjects:

I'm still learning Scala, but hope this helps! :)

1 Comment

Your answer contains much information and is very helpful. Thank you. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.