Scala Multiple Nested Case Clases - scala

Good day everyone, I create the following case class on SCALA:
sealed abstract class Value;
case class U(name: String) extends Value
case class L(name: String) extends Value
case class B(name: String) extends Value
sealed abstract class Term
case class Var(name: String) extends Term //variable name
case class Val(value: Value) extends Term //value
sealed abstract class Pattern //patterns
case class BGP(subject: Term, predicate: Term, obj: Term) extends Pattern
case class And( pat1: Pattern, pat2: Pattern) extends Pattern
case class Filter(pred: Predicate, pattern: Pattern ) extends Pattern
def function(p: Pattern): Unit = p match {
case BGP(Var(x), Val(y), Val(z)) => {
val con:conv = new conv()
val valor:Value = Val(y).value
}
Then, as you can see, BGP contains Term and extends to pattern, Val contains Values and extends to Term, and U,L,B contains Strings and extends to Value,
In my function I want to access to the strings that contains the U or L or B case classes, the variable valor = Val(y).value contains a U class for example, but when I write valor.XXXX don't appear me the name option. The big question is How can I do to accesss to the String name from U?

You just define it on Value which btw could be a trait.
sealed trait Value {
def name: String
}
case class U(name: String) extends Value
case class L(name: String) extends Value
case class B(name: String) extends Value

Related

Complex Sum Type in Scala

I have the following Type that i need to model:
sealed trait FieldType
case object INT extends FieldType
case object UINT extends FieldType
case object FLOAT extends FieldType
case object DOUBLE extends FieldType
case object BOOL extends FieldType
case object STRING extends FieldType
case object DATETIME extends FieldType
case class LIST(fieldType: FieldType) extends FieldType
case class SET(fieldType: FieldType) extends FieldType
The Issue i have is that in fact LIST and SET are actually ComplexFieldType that contain FieldType. In other words LIST Can Not Contain List or SET, same thing for SET.
What would be the proper way to model that, to ensure exhaustivity issue i.e. having the compiler telling me when i am missing some values.
I tried to introduce intermediary sealed trait as in SimpleFieldType and ComplexFieldType but then the pattern matching was messed up.
Only solution that i see if I don't want to compound things as in
case object LIST_INT
is to use smart constructor for LIST and SET.
However I thought drop a note and see what the scalaSphere knows about it.
It works indeed as such:
sealed trait FieldType
sealed trait SimpleFieldType extends FieldType
case object INT extends SimpleFieldType
case object UINT extends SimpleFieldType
case object FLOAT extends SimpleFieldType
case object DOUBLE extends SimpleFieldType
case object BOOL extends SimpleFieldType
case object STRING extends SimpleFieldType
case object DATETIME extends SimpleFieldType
sealed trait ComplexFieldType extends FieldType
case class LIST(fieldType: SimpleFieldType) extends ComplexFieldType
case class SET(fieldType: SimpleFieldType) extends ComplexFieldType
val field1: FieldType = INT
field1 match {
case FLOAT =>
case BOOL =>
case INT =>
case UINT =>
case DATETIME =>
case DOUBLE =>
case STRING =>
case LIST(_) =>
case SET(_) =>
}
ScalaC detect the non-exhaustiveness. I just had to use https://github.com/rtimush/sbt-rewarn#sbt-rewarn as the recompilation just skip it

Scala: Case classes with shared parameter?

I don't know if there's a way to do this, but I want to be able to specify that a set of case classes all share a parameter (so I can access it without pattern matching).
EDIT: After some help I have
abstract class Test(val termName : String)
case class TestOne(value : Int, name : String = null) extends Test(name)
case class TesTwo(otherValue : Boolean, name : String = null) extends Test(name)
Which is almost exactly what I want, though it would be nice to get rid of the ugliness of having both name and termName.
though it would be nice to get rid of the ugliness of having both name and termName.
Just make it a normal member of the supertype (which can easily be a trait), not a constructor parameter:
trait Test {
val name : String
}
case class TestOne(value : Int, name : String = null) extends Test
case class TestTwo(otherValue : Boolean, name : String = null) extends Test
(The standard Scala style is name: String, no space before :.)
If every implementation should have a separate, distinct implementation, declare abstract member and implement it in children:
abstract trait NamedCaseClass {
def name: String
}
case class OneCase(number : Int) extends NamedCaseClass {
override def name: String = "OneCase"
}
case class OtherCase(truth : Boolean) extends NamedCaseClass {
override def name: String = "OtherCase"
}
If all implementations could just use some value that you can calculate on creation, you can use abstract class constructor:
abstract class NamedCaseClass(val name: String)
case class OneCase(number : Int) extends NamedCaseClass("OneCase")
case class OtherCase(truth : Boolean) extends NamedCaseClass("OtherCase")
If you have a sealed hierarchy you could also define it like this:
sealed trait NamedCaseClass {
def nameOpt: Option[String] = this match {
case OneCase(number) => Some(name.toString)
case OtherCase(_) => None
}
}
case class OneCase(number : Int) extends NamedCaseClass
case class OtherCase(truth : Boolean) extends NamedCaseClass
Which one is more convenient pretty much depend on if you have a sealed hierarchy or open, if you can calculate value on creation or is this something more complicated that would work better as a method.

Exhaustive match on possible object values

First the code:
object MyEnums {
sealed abstract class MyEnum(val value: String)
case object First extends MyEnum("Some_ugly_looking_value1")
case object Second extends MyEnum("Some_ugly_looking_value2")
case object Third extends MyEnum("Some_ugly_looking_value3")
case object Fourth extends MyEnum("Some_ugly_looking_value4")
def fromString(value: String): Option[MyEnum] =
value match {
case First.value => Option(First)
case Second.value => Option(Second)
case Third.value => Option(Third)
case Fourth.value => Option(Fourth)
case _ => None
}
}
What I'm trying to achieve here is to be able to parse a string value coming from the outside into the form of the above enum. At the same time I would like to have the exhaustive pattern matching compiler warning if I don't cover all options in the match expression. What options do I have here? I don't like what I implemented above, since if this enum grows I may just forget to implement the new case clause...
Consider enumeratum like so
import enumeratum._
sealed abstract class MyEnum(override val entryName: String) extends EnumEntry
object MyEnum extends Enum[MyEnum] {
val values = findValues
case object First extends MyEnum("Some_ugly_looking_value1")
case object Second extends MyEnum("Some_ugly_looking_value2")
case object Third extends MyEnum("Some_ugly_looking_value3")
case object Fourth extends MyEnum("Some_ugly_looking_value4")
}
MyEnum.withName("Some_ugly_looking_value1") // res1: MyEnum = First
Now we do not have to fiddle with pattern match when adding a new case object.

Possible ways to pass argument of different type to case class

I want to group elements of different types into one.
Following is one example
trait Element
case class ElementString(key:String,value:String) extends Element
case class ElementDouble(key:String,value:Double) extends Element
case class ElementInt(key:String,value:Int) extends Element
Grp(ElementString("2","abc"),ElementDouble("3",100.20),ElementInt("4",10))
One possible way is to use varargs case class Grp(group:Element*).
Is there any other efficient way to achieve the above .
Any possible way to add elements one by one into Grp
Updated
I would also like to create a Group inside a Group.
A DSL like this is very common in scala because it is type-safe, but also very concise to use:
trait Value
object Value {
case class StringValue(value: String) extends Value
case class DoubleValue(value: Double) extends Value
case class IntValue(value: Int) extends Value
}
case class Element(key: String, value: Value)
object Element {
implicit def fromStringPair (a: (String,String)) = Element(a._1, Value.StringValue(a._2))
implicit def fromDoublePair (a: (String,Double)) = Element(a._1, Value.DoubleValue(a._2))
implicit def fromIntPair (a: (String,Int)) = Element(a._1, Value.IntValue(a._2))
}
case class Grp (elements: Element*)
Grp(
"2" -> "abc",
"3" -> 100.20,
"4" -> 10
)
//: Grp = Grp(WrappedArray(Element(2,StringValue(abc)), Element(3,DoubleValue(100.2)), Element(4,IntValue(10))))
Alternative, no varargs:
trait Value
// define these in different files if you want
case class Student(value: String) extends Value
case class Employee(value: Double) extends Value
case class Department(value: Int) extends Value
case class Element(key: String, value: Value)
case class Grp (elements: List[Element] = Nil) extends Value {
def add (key: String, value: Value): Grp = Grp(this.elements ++ List(Element(key, value)))
}
Grp()
.add("2", Student("abc"))
.add("3", Employee(100.20))
.add("4", Department(10))
.add("5", Grp().add("2", Student("xyz"))) // nested group
You can use a quasi builder pattern by adding the a function:
def withElement(elem: Element) = copy(group = group :+ elem)
Assuming group is a list. Note that this does make a new copy of the case class each time you call withElement. The code would then look like:
Grp().withElement(...).withElement(...)
You could create a real builder pattern if performance was important.

Generic enum using case class in scala

I have created the following enum objects
sealed trait MsgMapping[T] {def mycode: T;}
object Type1 {
sealed trait msg[Int] extends MsgMapping[Int]
case object A extends msg[Int]{val myCode = 0;}
case object B extends msg[Int]{val myCode = 1;}
}
object Type2 {
sealed trait msgtype[String] extends MsgMapping[String]
case object C extends msgtype[String]{val myCode = "xyz";}
case object D extends msgtype[String]{val myCode = "def";}
}
I want to create a generic case class that can except any type of MessageMapping ,it can be an Integer/String or any data type
But this line gives error as it expects the type.
case class EumType(valueType: MsgMapping [T])
The below works
case class EumType1(valueType: MsgMapping [Int])
case class EumType2(valueType: MsgMapping [String])
case class TestEnum(value:EumType1)
case class Test(val:TestEnum)
But I do not want to create EumType1 and EumType2 .Can anyone help to me to create a generic code for this
Update
As per suggestion
case class EnumType[T](valueType: MsgMapping[T])
case class TestEnum(value:EnumType[T])
It will throw compile error since it expects type
here but i want to pass the type on this line
case class Test(val:TestEnum) ,whether it is Type1 /Type2
Try using an existential type:
case class EumType(valueType: MessageMapping [_])