tonicebrian
tonicebrian

Reputation: 4795

How to do type inference with enums in Scala?

I have different kinds of enumerations in this flavour

class Gender extends Enumeration {
    type Gender = Value
    val Male,Female = Value
}

and I would like to have a generic function that given an element of an enumeration, it puts a 1 in an array of length .maxId (if you are familiar with R, I'm trying to implement factor). But I'm not able to get the types right, my function would be something like this (wrong) code:

def toFactor[T](elem:T.Value):List[Double] = {
  var array = Array.fill(T.maxId)(0.0)
  array(elem.id) == 1.0
  array.toList
}

How would you write this code so is generic for whatever enumeration we use?

Upvotes: 0

Views: 263

Answers (1)

tenshi
tenshi

Reputation: 26576

This code should do it:

object Gender extends Enumeration {
    type Gender = Value
    val Male, Female = Value
}

def toFactor[E <: Enumeration, V <: E#Value](enum: E, elem: V): List[Double] = {
  var array = Array.fill(enum.maxId)(0.0)
  array(elem.id) = 1.0
  array.toList
}

println(toFactor(Gender, Gender.Female)) // prints: List(0.0, 1.0)

You need to use E#Value instead of E.Value because it generally tells: any Value of the provided Enumeration E. E <: Enumeration restricts E to be subclass of Enumeration. You also need enum instance in order to get maxId.

Update

You can also simplify toFactor method a little bit and avoid using any Arrays or ids:

def toFactor[T <: Enumeration, V <: T#Value](enum: T, elem: V): List[Double] = 
      enum.values.toList map (curr => if (curr == elem) 1.0 else 0.0)

Upvotes: 1

Related Questions