Scala "or" in generic bounds - scala

I know that I can write something like this:
case class Something[T <: Foo with Bar](state: T)
This accepts classes which have the traits (or class and trait) Foo and Bar. This is an AND example where it is needed to extend both Foo and Bar. Is there an option which allows me to pass classes extending Foo OR Bar to pattern match against them?
The use case is that I have multiple Classes with different behaviors which consume states which are of shared types:
trait FooState
trait BarState
trait BazState
case class Foo(state: FooState) // must not accept BarState or BazState
case class Bar(state: BarState) // must not accept FooState or BazState
case class Baz(state: BazState) // must not accept FooState or BarState
case class FooBar(state: FooState or BarState) // must not accept BazState
case class FooBaz(state: FooState or BazState) // must not accept BarState
case class BarBaz(state: BarState or BazState) // must not accept FooState
I know I can create another trait for every compound class, but this would force me to add it to everything that extends any of these previous traits.

Yes, you would usually use a typeclass to achieve what you want, and a context bound. Here's how:
trait Acceptable
object Acceptable {
implicit val fooIsGood = new Acceptable[Foo] {}
implicit val barIsGood = new Acceptable[Bar] {}
}
case class Something[T : Acceptable](state: T)
And you can play with it to implement whatever functionality you want using this pattern. Achieving a real union type bound be done with Either or co-products, but in most scenarios this may be simpler.

One possible way to do this is to use the Either type:
case class FooBar(state: Either[FooState, BarState]) {
def someOperation() = {
state match {
case Left(fooState) => ???
case Right(barState) => ???
}
}
}
What you've described is a union type. The current version of Scala does not support them as you've described them, however it is planned for Dotty.
If you need more flexibility than that (more than two types for example) consider using a Coproduct from a functional programming library. Scalaz, Cats and Shapeless all expose them.

Related

Define common copy for a class hierarchy with many case classes

I would like to define a class hierarchy with about 100 case classes deriving from common base. The types are describing nodes in the AST hierarchy, like this one. I would like to do something along the lines of:
trait Base {
def doCopy: Base
}
trait CloneSelf[T <: CloneSelf[T]] extends Base {
self: T =>
def copy(): T
override def doCopy: T = copy()
}
case class CaseA(a: String) extends Base with CloneSelf[CaseA]
case class CaseB(b: Int) extends Base with CloneSelf[CaseB]
This gives an error, because the existence of my copy prevents the case classes from defining the automatic copy. Is there some way how to implement the "clone" doCopy so that is uses the automatic copy of those case classes?
I would like to define a class hierarchy with about 100 case classes deriving from common base.
Please do not do that, you should absolutely find a pattern to avoid it! If you want to do this anyway... Try ducktyping:
trait CloneSelf[T <: {def copy(): T}] {
self: T =>
override def doCopy: T = copy()
}
I cannot test now so this probably won't compile, but you can figure it out by yourself with the general idea!
Edit:
Why having 100 subclasses is evil: imagine you perform one change in the base class, for instance change its name from Base to BaseCloning -> you'll have to change it in EVERY child class (100 changes).
How you will avoid that depends on what you want to do with your classes, check creationnal and structural patterns: factory, builder, prototype, flyweight, composite... Always think about "how much work will I have if I change something in the base class? Will it affect all children?"
I have found out defining the doCopy in each case class is actually less work than defining each class to inherit from CloneSelf. The code looks like this:
trait Base {
def doCopy: Base
}
case class CaseA(a: String) extends Base {
def doCopy = copy()
}
case class CaseB(b: Int) extends Base {
def doCopy = copy()
}
I was surprised to learn that without explicit type on the overridden method the type is inferred by the compiler, therefore the static type of CaseA("a").doCopy is the same as of CaseA("a").copy(), i.e. CaseA, not Base. Adding explicit type for each case class would be probably more obvious, but this would require more work compared to just copy-pasting the same line into each of them. Not that it matters much - when I do copying via the case class type, I may use the copy() as well. It is only when I have the Base I need the doCopy, therefore declaring it like def doCopy: Base = copy() would do little harm.

What is the difference between mixins and inheritance?

I am trying to understand the Mixins in the context of scala. In particular I wanted to know difference between concepts of inheritance and Mixins.
The definition of Mixin in wiki says :
A mixin class acts as the parent class, containing the desired functionality. A subclass can then inherit or simply reuse this functionality, but not as a means of specialization. Typically, the mixin will export the desired functionality to a child class, without creating a rigid, single "is a" relationship. Here lies the important difference between the concepts of mixins and inheritance, in that the child class can still inherit all the features of the parent class, but, the semantics about the child "being a kind of" the parent need not be necessarily applied.
In the above definition, I am not able to understand the statements marked in bold. what does it mean that
A subclass can inherit functionality in mixin but not as a means of specialization
In mixins, the child inherits all features of parent class but semantics about the child "being a kind" the parent need not be necessarily applied. - How can a child extend a parent and not necessarily a kind of Parent ? Is there an example like that.
I'm not sure I understood your question properly, but if I did, you're asking how something can inherit without really meaning the same thing as inheriting.
Mixins, however, aren't inheritance – it's actually more similar to dynamically adding a set of methods into an object. Whereas inheritance says "This thing is a kind of another thing", mixins say, "This object has some traits of this other thing." You can see this in the keyword used to declare mixins: trait.
To blatantly steal an example from the Scala homepage:
abstract class Spacecraft {
def engage(): Unit
}
trait CommandoBridge extends Spacecraft {
def engage(): Unit = {
for (_ <- 1 to 3)
speedUp()
}
def speedUp(): Unit
}
trait PulseEngine extends Spacecraft {
val maxPulse: Int
var currentPulse: Int = 0
def speedUp(): Unit = {
if (currentPulse < maxPulse)
currentPulse += 1
}
}
class StarCruiser extends Spacecraft
with CommandoBridge
with PulseEngine {
val maxPulse = 200
}
In this case, the StarCruiser isn't a CommandoBridge or PulseEngine; it has them, though, and gains the methods defined in those traits. It is a Spacecraft, as you can see because it inherits from that class.
It's worth mentioning that when a trait extends a class, if you want to make something with that trait, it has to extend that class. For example, if I had a class Dog, I couldn't have a Dog with PulseEngine unless Dog extended Spacecraft. In that way, it's not quite like adding methods; however, it's still similar.
A trait (which is called mixin when mixed with a class) is like an interface in Java (though there are many differences) where you can add additional features to a class without necessarily having "is a" relationship. Or you can say that generally traits bundle up features which can be used by multiple independent classes.
To give you an example from Scala library, Ordered[A] is a trait which provides implementation for some basic comparison operations (like <, <=, >, >=) to classes that can have data with natural ordering.
For example, let's say you have your own class Number and subclasses EvenNumber and OddNumber as shown below.
class Number(val num : Int) extends Ordered[Number] {
override def compare(that : Number) = this.num - that.num
}
trait Half extends Number {
def half() = num / 2
}
trait Increment extends Number {
def increment() = num + 1
}
class EvenNumber(val evenNum : Int) extends Number(evenNum) with Half
class OddNumber(val oddNum : Int) extends Number(oddNum) with Increment
In the example above, classes EvenNumber and OddNumber share is a relationship with Number but EvenNumber does not have "is a" relation with Half neither OddNumber share "is a" relation with Increment.
Another important point is even though class Number uses extends Ordered syntax, it means that Number has an implicit is a relationship with superclass of Ordered ie Any.
I think its very usage dependent. Scala being a multi-paradigm language makes it powerful as well as a bit confusing at times.
I think Mixins are very powerful when used the right way.
Mixins should be used to introduce behavior and reduce bolierplate.
A trait in Scala can have implementations and it is tempting to extend them and use them.
Traits could be used for inheritance. It can also be called mixins however that in my opinion is not the best way to use mixin behavior. In this case you could think of traits as Java Abstract Classes. Wherein you get subclasses that are "type of" the super class (the trait).
However Traits could be used as proper mixins as well. Now using a trait as a mixin depends on the implementation that is "how you mix it in". Mostly its a simple question to ask yourself . It is "Is the subclass of the trait truly a kind of the trait or are the behaviors in the trait behaviors that reduce boilerplate".
Typically it is best implemented by mixing in traits to objects rather than extending the trait to create new classes.
For example consider the following example:
//All future versions of DAO will extend this
trait AbstractDAO{
def getRecords:String
def updateRecords(records:String):Unit
}
//One concrete version
trait concreteDAO extends AbstractDAO{
override def getRecords={"Here are records"}
override def updateRecords(records:String){
println("Updated "+records)
}
}
//One concrete version
trait concreteDAO1 extends AbstractDAO{
override def getRecords={"Records returned from DAO2"}
override def updateRecords(records:String){
println("Updated via DAO2"+records)
}
}
//This trait just defines dependencies (in this case an instance of AbstractDAO) and defines operations based over that
trait service{
this:AbstractDAO =>
def updateRecordsViaDAO(record:String)={
updateRecords(record)
}
def getRecordsViaDAO={
getRecords
}
}
object DI extends App{
val wiredObject = new service with concreteDAO //injecting concrete DAO to the service and calling methods
wiredObject.updateRecords("RECORD1")
println(wiredObject.getRecords)
val wiredObject1 = new service with concreteDAO1
wiredObject1.updateRecords("RECORD2")
println(wiredObject1.getRecords)
}
concreteDAO is a trait which extends AbstractDAO - This is inheritance
val wiredObject = new service with concreteDAO -
This is proper mixin behavior
Since the service trait mandates the mixin of a AbstractDAO. It would be just wrong for Service to extend ConcreteDAO anyways because the service required AbstractDAO it is not a type of AbstractDAO.
Instead you create instances of service with different mixins.
The difference between mixin and inheritance is at semantic level. At syntax level they all are the same.
To mix in a trait, or to inherit from a trait, they all use extends or with which is the same syntax.
At semantic level, a trait that is intended to be mixed in usually doesn't have a is a relationship with the class mixining it which differs to a trait that is intended to be inherited.
To me, whether a trait is a mixin or parent is very subjective, which often time is a source of confusion.
I think it is talking about the actual class hierarchy. For example, a Dog is a type of Animal if it extends from the class (inheritance). It can be used wherever an Animal parameter is applicable.

How to design immutable model classes when using inheritance

I'm having trouble finding an elegant way of designing a some simple classes to represent HTTP messages in Scala.
Say I have something like this:
abstract class HttpMessage(headers: List[String]) {
def addHeader(header: String) = ???
}
class HttpRequest(path: String, headers: List[String])
extends HttpMessage(headers)
new HttpRequest("/", List("foo")).addHeader("bar")
How can I make the addHeader method return a copy of itself with the new header added? (and keep the current value of path as well)
Thanks,
Rob.
It is annoying but the solution to implement your required pattern is not trivial.
The first point to notice is that if you want to preserve your subclass type, you need to add a type parameter. Without this, you are not able to specify an unknown return type in HttpMessage
abstract class HttpMessage(headers: List[String]) {
type X <: HttpMessage
def addHeader(header: String):X
}
Then you can implement the method in your concrete subclasses where you will have to specify the value of X:
class HttpRequest(path: String, headers: List[String])
extends HttpMessage(headers){
type X = HttpRequest
def addHeader(header: String):HttpRequest = new HttpRequest(path, headers :+header)
}
A better, more scalable solution is to use implicit for the purpose.
trait HeaderAdder[T<:HttpMessage]{
def addHeader(httpMessage:T, header:String):T
}
and now you can define your method on the HttpMessage class like the following:
abstract class HttpMessage(headers: List[String]) {
type X <: HttpMessage
def addHeader(header: String)(implicit headerAdder:HeaderAdder[X]):X = headerAdder.add(this,header) }
}
This latest approach is based on the typeclass concept and scales much better than inheritance. The idea is that you are not forced to have a valid HeaderAdder[T] for every T in your hierarchy, and if you try to call the method on a class for which no implicit is available in scope, you will get a compile time error.
This is great, because it prevents you to have to implement addHeader = sys.error("This is not supported")
for certain classes in the hierarchy when it becomes "dirty" or to refactor it to avoid it becomes "dirty".
The best way to manage implicit is to put them in a trait like the following:
trait HeaderAdders {
implicit val httpRequestHeaderAdder:HeaderAdder[HttpRequest] = new HeaderAdder[HttpRequest] { ... }
implicit val httpRequestHeaderAdder:HeaderAdder[HttpWhat] = new HeaderAdder[HttpWhat] { ... }
}
and then you provide also an object, in case user can't mix it (for example if you have frameworks that investigate through reflection properties of the object, you don't want extra properties to be added to your current instance) (http://www.artima.com/scalazine/articles/selfless_trait_pattern.html)
object HeaderAdders extends HeaderAdders
So for example you can write things such as
// mixing example
class MyTest extends HeaderAdders // who cares about having two extra value in the object
// import example
import HeaderAdders._
class MyDomainClass // implicits are in scope, but not mixed inside MyDomainClass, so reflection from Hiberante will still work correctly
By the way, this design problem is the same of Scala collections, with the only difference that your HttpMessage is TraversableLike. Have a look to this question Calling map on a parallel collection via a reference to an ancestor type

Rename and Override equals method in case class

I want to define a trait named Ext that renames the existing equals method to equalsByAttributes and defines a new equals method at the same time. The trait is used
to extend case classes. My current solution looks somehow hacky:
case class A(id: Int) extends Ext
trait Ext { p: Product =>
// new implementation
override def equals(obj: Any) = obj match {
case that: AnyRef => this eq that
case _ => false
}
// reimplementation of old equals implementation
def equalsByAttributes(obj: Any) = obj match {
case that: Product =>
if (this.getClass.isAssignableFrom(that.getClass) || that.getClass.isAssignableFrom(this.getClass))
p.productIterator.toList == that.productIterator.toList
else
false
case _ => false
}
}
I wonder if there is a direct way to reference A's equals method in equalsByAttributes so that one can avoid the reimplementation of this method?
Edit 2012-07-12
Since there is a solution for referencing super implementations with super.METHOD_NAME I thought there must be a similar syntax such as overridden.METHOD_NAME for accessing specific implementations in the base class/trait that is going to be extended by the trait, so that my Ext trait would look like this:
trait Ext { p: Product =>
override def equals(obj: Any) = ...
def equalsByAttributes(obj: Any) = overridden.equals(obj)
}
Do not change equals on case classes. If you need to do so, do not make your classes case classes. Changing case class methods will make the code behave unexpectedly (that is, unlike case classes), which will increase maintenance cost, break everything that assumes case classes work like case classes, make people's life miserable and get a lot of programmers to hate your guts.
In other words, it's not worth it. Don't do that.
The compiler will not generate equals (and hashCode, respectively) for case classes that already come with an equals, i.e., that inherit one or declare one themselves. Read more about this in this blog entry. AFAIK the only thing you can do is to implement structural equality by using productIterator provided by the Product trait that case classes extend, just as you did in equalsByAttributes.
This code will use the method implementation from the Ext trait:
case class A(id: Int) extends Ext {
def someEqual(x:Any) = {
super[Ext].equalsByAttributes(x)
}
}
The super[X] here is used to refer to one of the the traits this class extends. This answers your second questions.
For your first question:
trait Ext { p: A => def eql(x:Any) = p.equals(x) }

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.