2

I thought it should be possible to write a generic function that works for all Enumeration values. I tried a simple parser first but I failed:

object Weekday extends Enumeration {
  type Weekday = Value

  val MONDAY = Value("MONDAY")
  val OTHER = Value("OTHER")

  implicit def valueToWeekday(v: Value): Weekday = v.asInstanceOf[Weekday]
  implicit def stringToWeekday(s: String): Weekday = Weekday.withName(s)
}

object Enumerations {
  import Weekday._
  println("Welcome to the Scala worksheet")

  def parseEnumeration[T <: Enumeration](s: String)(implicit ev: T): T#Value = {
    ev.withName(s)
  }

 val test = parseEnumeration[Weekday]("MONDAY")
}

So how can I write a generict function taking an enumeration type as parameter and returning a Value of that type? I'm a bit confused here with the Object and the inner type with the same name.

1

1 Answer 1

3

Firstly, your implicit method valueToWeekday doesn't really do anything, as Weekday is simply an alias for Value in this context.

Secondly, your implicit method stringToWeekday is a working, albeit non-generic conversion from a string to its enumeration value.

However, it is not hard to make stringToWeekday generic. You simply need to pass the enumeration to the function, just like you do in parseEnumeration. Since you made the evidence in parseEnumeration implicit, all you need to do is put an appropriate implicit value in the context. Alternatively, you can pass the evidence explicitly.

So you can remove those implicit conversions (and the type alias, since the name-clash is slightly misleading).

object Weekday extends Enumeration {
  val Monday = Value("MONDAY")
  val Other = Value("OTHER")
}
  1. The implicit way:

    def parseEnumeration[T <: Enumeration](s: String)(implicit ev: T): T#Value = ev.withName(s)
    
    implicit val evidence = Weekday
    val weekday = parseEnumeration("MONDAY") // results in the value Weekday.Monday
    
  2. The explicit way:

    def parseEnumeration[T <: Enumeration](s: String, enumeration: T): T#Value = enumeration.withName(s)
    
    val weekday = stringToEnumerationValue("MONDAY", Weekday) // results in the value Weekday.Monday
    

A third option would be to use a ClassTag as evidence, which is put in the context by the compiler through the generic parameters. However, this requires reflection to actually call the method withName and I would discourage going this way.

Sign up to request clarification or add additional context in comments.

Comments

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.