Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restrict Scala type to be one of a set of types

Tags:

generics

scala

Is there a way to define a generic type parameter that can be one of a small set of types? I want to define a type T that can only be one of {Int, Long, Float, Double}.

like image 289
user1094206 Avatar asked Jan 20 '16 17:01

user1094206


1 Answers

Daniel Landgon's comment above points in the right direction.
In case someone is in a hurry to click the link though:

@annotation.implicitNotFound("It can not be proven that ${T} is of type Int, Long, Float or Double")
sealed trait Foo[T]

object Foo {
  implicit val intFoo: Foo[Int] = new Foo[Int]{}  
  implicit val LongFoo: Foo[Long] = new Foo[Long]{}
  implicit val FloatFoo: Foo[Float] = new Foo[Float]{}
  implicit val DoubleFoo: Foo[Double] = new Foo[Double]{}
}

With:

def bar[T](t: T)(implicit ev: Foo[T]): Unit = println(t)

We get:

bar(5)        // res: 5
bar(5.5)      // res: 5.5
bar(1.2345F)  // res: 1.2345

bar("baz")    // Does not compile. Error: "It can not be proven that String is of type Int, Long, Float or Double"
bar(true)     // Does not compile. Error: "It can not be proven that Boolean is of type Int, Long, Float or Double"

This could also be achieved with Miles Sabin's union type as provided in his shapeless library.

like image 69
cmhteixeira Avatar answered Nov 08 '22 01:11

cmhteixeira