Reputation: 1802
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?
Upvotes: 1
Views: 1290
Reputation: 7845
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
Upvotes: 0
Reputation: 51271
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
Upvotes: 3