How to deal with enumerations and path-dependent types in Scala

635 views Asked by At

I'm having a problem whose solution should be equivalent to the solution to this: Suppose I want to write a method which, given an Enumeration, returns a list of all its values. I want to write:

def makeList[E <: Enumeration](enum: E): List[enum.Value] = enum.values.toList

but compilation fails with an illegal dependent method type error. Is it OK to write this instead?

def makeList[E <: Enumeration](enum: E): List[E#Value] = enum.values.toList
2

There are 2 answers

1
James Iry On BEST ANSWER

You can use a path dependent type there but it's an experimental feature right now. Use -Xexperimental for scala or scalac.

$ scala -Xexperimental
Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_21).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def makeList[E <: Enumeration](enum: E): List[enum.Value] = enum.values.toList
makeList: [E <: Enumeration](enum: E)List[enum.Value]

scala> object Bool extends Enumeration { 
     |   type Bool = Value
     |   val True, False = Value 
     | }
defined module Bool

scala> makeList(Bool)
res0: List[Bool.Value] = List(True, False)
1
Alexey Romanov On

It seems to be OK to me:

object WeekDay extends Enumeration { 
  type WeekDay = Value 
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value 
}

> makeList(WeekDay)
res2: List[WeekDay#Value] = List(Mon, Tue, Wed, Thu, Fri, Sat, Sun)

> makeList(WeekDay.Mon)
error: inferred type arguments [WeekDay.Value] do not conform to method makeList's type parameter bounds [E <: Enumeration]
       makeList(WeekDay.Mon)
       ^

UPDATE in reply to the comment:

I guess someone could override the Value nested class instead of Val (I just looked at the source and it isn't sealed), but I can't think of a reason to. Note that normally, for all enumerations, Value is the same type:

object Bool extends Enumeration { 
  type Bool = Value
  val True, False = Value 
}

> Bool.True.getClass
res8: java.lang.Class[_] = class scala.Enumeration$Val
> Bool.True.getClass == WeekDay.Mon.getClass
res7: Boolean = true