Search code examples
scalaalgebraic-data-typesgadtscala-3

scala3: Methods on enum case, possible?


I'm trying to define an ADT (tagged union type, actually).

enum MyEnum{
  case MyFirstCase(value:String) extends MyEnum{
    def someMethod = "whatever"
  }

}

But the compiler complains... Is it possible to add methods specific cases of a Scala3 enum (GADT)?

Or do we have to rely with the usual sealed trait encoding?


Solution

  • It is possible with extension methods! See the example below.

    The compiler will infer the enum type (here MyEnum) instead of the precise case type (here MyEnum.A.type in the example), so you need to specify it yourself in some cases.

    enum MyEnum:
      case A
    
    extension (a: MyEnum.A.type)
      def specificMethod() = println("ok")
    
    MyEnum.A.specificMethod() // works
    
    val preciseA: MyEnum.A.type = MyEnum.A
    preciseA.specificMethod() // works
    
    val unpreciseA = MyEnum.A // inferred type: MyEnum
    unpreciseA.specificMethod() // compile error (specificMethod is not part of MyEnum)
    

    Note that Scala 3 also provide union types in the following form, which may be easier to use in your case:

    type MyUnion = A | B
    
    // and then you can define A and B with the methods you want
    class A:
      def specificToA()
    
    class B:
      def specificToB()