1
votes

let's say I have:

sealed trait Data
final case class TextData()  extends Data
final case class ImageData() extends Data
final case class MetaData[D <: Data](data: D) extends Data

I want to pattern match Data objects. I have defined:

def getDataTypeName(data: Data): String ={
    data match {
        case TextData()=>"text"
        case ImageData()=>"image"
        //MetaData(MetaData(_))=>"metaMeta1"  //a
        case _:MetaData[MetaData[_]]=>"metaMeta2"  //b
        //case MetaData(data:Data)=>"meta"+ getDataTypeName(data) //c
        //MetaData(TextData(_))=>"metaMeta1"  //d
        case MetaData(_)=>"meta"
    }
}

I want to be able to see if my data is a meta-metadata, meta-TextData, etc. Line a give me an error, saying:

constructor cannot be instantiated to expected type; found : inst$A$A.MetaData[D] required: A$A115.this.Data case MetaData(MetaData(_))=>"metaMeta1"

I would prefer to have something resembling line a. alternatively something like line c would be nice too.

I also tried line b. This one generates some warnings:

non-variable type argument A$A115.this.MetaData[] in type pattern A$A115.this.MetaData[A$A115.this.MetaData[]] is unchecked since it is eliminated by erasure case :MetaData[MetaData[]]=>"metaMeta" ^

I get this warning for both MetaData[_]s. My understanding is that the said pattern is reduced to _ after type erasure which is consistent with my test results.

I therefore want to know if there is a way of matching against MetaMetaData, MetaTextData ,MetaMetaMetaData etc.

Alternatively, is my design using sealed class in a way they shouldn't be used? What alternative design would you suggest?

2
i assume that match against MetaData, and then match again to check the inner class is not your ideal solution? data match { case Metadata(x) => x match { ... } }pedrorijo91
I guess I would be happy with that too. In fact I did try doing something similar (line c), but couldn't get the syntax right.ShS

2 Answers

3
votes

I made a change to the MetaData() definition to make this work.

sealed trait Data
final case class TextData()  extends Data
final case class ImageData() extends Data
final case class MetaData(data: Data) extends Data

def printType(data: Data): String = data match {
  case TextData()=>"text"
  case ImageData()=>"image"
  case MetaData(d)=>"meta:" + printType(d)
}

val md = MetaData( MetaData(TextData()) )
printType(md)  // res0: String = meta:meta:text
0
votes
  sealed trait Data
  final case class TextData()  extends Data
  final case class ImageData() extends Data
  final case class MetaData[D <: Data](data: D) extends Data

and

def getDataTypeName(data: Data): String ={
    data match {
      case TextData()=>"text"
      case ImageData()=>"image"
      case MetaData(MetaData(_))=> "metaMeta1" 
      case MetaData(TextData())=> "textMeta1"  
      case MetaData(ImageData())=> "imgMeta1"  
    }
  }

testing on REPL:

scala> getDataTypeName(TextData())
res1: String = text

scala> getDataTypeName(MetaData(TextData()))
res2: String = textMeta1

scala> getDataTypeName(MetaData(MetaData(TextData())))
res3: String = metaMeta1