Getting all enum-y case object values in Scala - scala

In Scala, enums are a disputed area and many people (including myself) rather use case objects than any library-based enumeration. This is great, except for that one doesn't get a list of all possible values, which sometimes is needed. I've maintained such lists (allKeys) manually, but that is tedious and error-prone.
The question is: how can Scala 2.11 TypeTags or reflection be used, to create such a list?
One of two ways would work:
getting all derived instances of a sealed class
getting all case objects declared within a particular object
Note: There are samples that seem to promise what I'm looking for. But that's overkill - there must be an almost one-liner to get the same?
Below is a test for this. How could I implement the allOf function?
class ManifestToolsTest extends UnitTest {
behavior of "ManifestTools" {
sealed class MyEnum
object MyEnum {
case object A extends MyEnum
case object B extends MyEnum
case object C extends MyEnum
val x= 10 // should not be listed
def f(x: Int) = x // should not be listed
}
def allOf[T]: Seq[T] = {
...
}
it should "be able to list the 'case object' members of an object" in {
val tmp: Seq[MyEnum] = allOf[MyEnum]
tmp should contain theSameElementsAs( List(MyEnum.A, MyEnum.B, MyEnum.C) )
}
}
}
I've tried to get this info from the Scala documentation, but when it comes to reflection, things are really abstract. I believe the above need is (should be) covered by Scala 2.11.
References:
Case objects vs Enumerations in Scala

I've found the cure, called Enumeratum, but thought I'd post this question anyhow to make it easier for people to find this new piece of macro jewelry.

Related

How to make an Scala Enumeration implement a Trait without modifying the original Enum?

I'm toying with Scala for the first time so bear with me. Also using tapir to declare an API, where I'm having issues providing a Schema for an enum.
I have a bunch of enums defined that are part of my domain model and that extend Scala's Enumeration. For instance, this is one of them:
object Status extends Enumeration with JsonEnumeration {
val Active, Completed, Archived, Deleted = Value
}
And also have many case classes that uses them. For instance, Order uses our previously defined enumeration, like:
case class Order(
id: String,
name: Option[String],
status: Status.Value,
)
I want to make this enum implement a trait that adds an implicit, but without modifying the original Status enumeration (I don't want to couple the Status enum -and all the others- to this trait).
The trait looks like:
import sttp.tapir.{Schema, Validator}
trait TapirEnumeration { e: Enumeration =>
implicit def schemaForEnum: Schema[e.Value] =
Schema.string.validate(Validator.enumeration(e.values.toList, v => Option(v)))
}
I wanted to somehow modify the Order object so the Status enum is now a TapirStatus enum (or something like that) which extends both the original Status and TapirEnumeration, but I don't think that can be doable, given that Status is originally defined as a companion object.
Ideally, all the enums I want to expose as responses from my API will implement that TapirEnumeration trait while still extending what they already extend.
What can I do to achieve this? Of course, creating a new enum that implements the trait isn't DRY so it's not an option.
Why does implicit need to be defined in the enum itself in the first place? Just make it its own definition.
import scala.language.implicitConversions
object EnumImplicits {
implicit def schema[E <: Enumeration](e: E): Schema[e.Value] = ???
}
Then, wherever you need access to that implicit you just make it available with import EnumImplicits._
Here is an example

Scala: Value Class vs Case Class

I'm trying to discover the differences between using a value class or a case class in a given scenario. Suppose I want to model the integers mod 5 as a unique datatype. The question is which one I should begin with...
class IntegerMod5(val value: Int) extends AnyVal
case class IntegerMod5(value: Int)
Regardless, it seems that I can create an implementation of Numeric fairly easily. With the case class approach, then, I can simply do this:
case class IntegerMod5(value: Int)(implicit ev: Numeric[IntegerMod5]) {
import ev.mkNumericOps
}
However, it seems to be a much more difficult endeavour with value classes, mainly as the benefit is to avoid object creation. Thus, something like
implicit class IntegersMod5Ops(value: IntegerMod5)(implicit ev: Numeric[IntegerMod5]) {
import ev.mkNumericOps
}
Would appear to largely defeat the purpose. (Not sure if it even works, actually.)
The question is that is it possible to use Numeric with a value class, or will I have to bite the bullet and use a case class?
You don't need implicit ev: Numeric[IntegerMod5] as an argument, just define it in the companion object:
object IntegerMod5 {
implicit val numeric: Numeric[IntegerMod5] = ...
}
It will be automatically picked up when you use arithmetic operations on IntegerMod5s, and because it's a val, it's only initialized once (you can use object as well).

Using value classes in scala to implement trait methods?

I have a trait that defines a function--I don't want to specify how it will work until later. This trait is mixed in with several case classes, like so:
trait AnItem
trait DataFormatable {
def render():String = "" // dummy implementation
}
case class Person(name:String, age:Int) extends DataFormatable with AnItem
case class Building(numFloors:Int) extends DataFormatable with AnItem
Ok, so now I want includable modules that pimp specific implementations of this render behavior. Trying to use value classes here:
object JSON {
implicit class PersonRender( val p:Person ) extends AnyVal {
def render():String = {
//render json
}
}
// others
}
object XML {
implicit class PersonRender( val p:Person ) extends AnyVal {
def render():String = {
//render xml
}
}
// others
}
The ideal use would look like this (presuming JSON output desired):
import JSON._
val p:AnItem = Person("John",24)
println(p.render())
All cool--but it doesn't work. Is there a way I can make this loadable-implementation thing work? Am I close?
The DataFormatable trait is doing nothing here but holding you back. You should just get rid of it. Since you want to swap out render implementations based on the existence of implicits in scope, Person can't have it's own render method. The compiler will only look for an implicit conversion to PersonRender if Person doesn't have a method named render in the first place. But because Person inherits (or is forced to implement) render from DataFormatable, there is no need to look for the implicit conversion.
Based on your edit, if you have a collection of List[AnItem], it is also not possible to implicitly convert the elements to have render. While each of the sub-classes may have an implicit conversion that gives them render, the compiler doesn't know that when they are all piled into a list of a more abstract type. Particularly an empty trait such as AnItem.
How can you make this work? You have two simple options.
One, if you want to stick with the implicit conversions, you need to remove DataFormatable as the super-type of your case classes, so that they do not have their own render method. Then you can swap out XML._ and JSON._, and the conversions should work. However, you won't be allowed mixed collections.
Two, drop the implicits altogether and have your trait look like this:
trait DataFormatable {
def toXML: String
def toJSON: String
}
This way, you force every class that mixes in DataFormatable to contain serialization information (which is the way it should be, rather than hiding them in implicits). Now, when you have a List[DataFormatable], you can prove all of the elements can both be converted to JSON or XML, so you can convert a mixed list. I think this would be much better overall, as the code should be more straightforward. What imports you have shouldn't really be defining the behavior of what follows. Imagine the confusion that can arise because XML._ has been imported at the top of the file instead of JSON._.

Reflection for nested classes

I see that most people who have been playing with ScalaSigParser, in an effort to ser/des idiomatic Scala case classes in a nice way, have avoided this issue, but I'd like to know if it's possible. I have a situation much like the following:
trait OuterTrait {
abstract class InnerAbstract(i: Int)
}
object OuterObject extends OuterTrait {
case class InnerConcrete(i: Int) extends InnerAbstract(i)
}
val bippy = OuterObject.InnerConcrete(123)
val s = serialize(bippy)
// time passes...
val obj = deserialize[OuterObject.InnerConcrete](s)
So, I can find the ScalaSig for OuterTrait, but I haven't managed to find a nice general way to identify the outer object from the InnerConcrete class. Any protips?
If the problem is navigating from the Class of the inner object to the Class of the outer object, the issue may be fixed in Scala trunk, one of the tickets concerned beeing SI-4983.

Pattern matching with generics

Given the following class pattern match:
clazz match {
case MyClass => someMethod[MyClass]
}
Is it possible to refer to MyClass in a generic way based on what the pattern match came up with? For example, if I have multiple subclasses of MyClass, can I write a simple pattern match to pass the matched type to someMethod:
clazz match {
case m <: MyClass => someMethod[m]
}
Unfortunately types are not really first class citizens in Scala. This means for example that you cannot do pattern matching on types. A lot of information is lost due to stupid type erasure inherited from the Java platform.
I don't know if there are any improvement requests for this, but this is one of the worst problems in my option, so someone should really come up with such a request.
The truth is you will need to pass around evidence parameters, at best in the form of implicit parameters.
The best I can think of goes in the line of
class PayLoad
trait LowPriMaybeCarry {
implicit def no[C] = new NoCarry[C]
}
object MaybeCarry extends LowPriMaybeCarry {
implicit def canCarry[C <: PayLoad](c: C) = new Carry[C]
}
sealed trait MaybeCarry[C]
final class NoCarry[C] extends MaybeCarry[C]
final class Carry[C <: PayLoad] extends MaybeCarry[C] {
type C <: PayLoad
}
class SomeClass[C <: PayLoad]
def test[C]( implicit mc: MaybeCarry[C]) : Option[SomeClass[_]] = mc match {
case c: Carry[_] => Some(new SomeClass[ c.C ])
case _ => None
}
but still I can't get the implicits to work:
test[String]
test[PayLoad] // ouch, not doin it
test[PayLoad](new Carry[PayLoad]) // sucks
So if you want to save yourself serous brain damage, I would forget about the project or look for another language. Maybe Haskell is better here? I'm still hoping that we can eventually match types, but my hopes are pretty low.
Maybe the guys from scalaz have come up with a solution, they pretty much exploited the type system of Scala to the limits.
Your code is not really clear, because at least in java clazz is a typical name for variables of type java.lang.Class and variations. I still believe that clazz is not an instance of Class but of your own class.
In Java and Scala, given an object o: AnyRef you can get access to its class at runtime via o.getClass: Class[_], and for instance create instances of that class through the Reflection API. However, type parameters are passed at compile-time, so you can't pass a type as-is at compile time. Either you use AnyRef all over the place as type (which will work, I assume) or you use the reflection API if you have more advanced needs.