Update immutable data structure through inheritance - scala

I'm making a strategic game and I try to apply what I learned, try to use immutable data. In my game I have Units, these units can have different special function. By exemple some plane can hide themselves. What I search is a way to be able to do some sort of
abstract class Units {
val life:Int
}
trait Hidable { self: Units =>
val hided:Boolean
def hide:Units with Hidable= ....
}
without having to copy paste:
def hide = copy(hided=true)
on every case class that mixin Hidable.

A common way to update an immutable data structure -- is using lenses.
There's a compiler plugin to generate lenses for your code, though it is not very production-ready. It is also available for an old scalaz only.
Here's a related question.

Related

Scala type alias with companion object

I'm a relatively new Scala user and I wanted to get an opinion on the current design of my code.
I have a few classes that are all represented as fixed length Vector[Byte] (ultimately they are used in a learning algorithm that requires a byte string), say A, B and C.
I would like these classes to be referred to as A, B and C elsewhere in the package for readability sake and I don't need to add any extra class methods to Vector for these methods. Hence, I don't think the extend-my-library pattern is useful here.
However, I would like to include all the useful functional methods that come with Vector without having to 'drill' into a wrapper object each time. As efficiency is important here, I also didn't want the added weight of a wrapper.
Therefore I decided to define type aliases in the package object:
package object abc {
type A: Vector[Byte]
type B: Vector[Byte]
type C: Vector[Byte]
}
However, each has it's own fixed length and I would like to include factory methods for their creation. It seems like this is what companion objects are for. This is how my final design looks:
package object abc {
type A: Vector[Byte]
object A {
val LENGTH: Int = ...
def apply(...): A = {
Vector.tabulate...
}
}
...
}
Everything compiles and it allows me to do stuff like this:
val a: A = A(...)
a map {...} mkString(...)
I can't find anything specifically warning against writing companion objects for type aliases, but it seems it goes against how type aliases should be used. It also means that all three of these classes are defined in the same file, when ideally they should be separated.
Are there any hidden problems with this approach?
Is there a better design for this problem?
Thanks.
I guess it is totally ok, because you are not really implementing a companion object.
If you were, you would have access to private fields of immutable.Vector from inside object A (like e.g. private var dirty), which you do not have.
Thus, although it somewhat feels like A is a companion object, it really isn't.
If it were possible to create a companion object for any type by using type alias would make member visibility constraints moot (except maybe for private|protected[this]).
Furthermore, naming the object like the type alias clarifies context and purpose of the object, which is a plus in my book.
Having them all in one file is something that is pretty common in scala as I know it (e.g. when using the type class pattern).
Thus:
No pitfalls, I know of.
And, imho, no need for a different approach.

How can I mix higher-kinds with "regular" generics for Typeclasses in Scala

I'm trying to write my own Typeclass in scala, to provide a mechanism to convert classes into an arbitrary "DataObject" (for which I'm using a Map below, however I don't want that to be important). Up until now I have the following:
type DataObject = Map[String, Any]
trait DataSerializer[A] {
def toDataObject(instance: A): DataObject
def fromDataObject(dataObject: DataObject): A
}
This works well for 'simple' classes, for which I can create a concrete class implementing this trait to act as my serializer. However, I thought it would also be nice to allow Collections/Containers to be serialized, without having to create a different implementation for every type that could be contained. I ended up with this:
trait DataCollectionSerializer[Collection[_]] {
def toDataObject[A: DataSerializer](instance: Collection[A]): DataObject
def fromDataObject[A: DataSerializer](dataObject: DataObject): Collection[A]
}
ie. a collection can be serialized if it's contents can be serialized.
Again, this works well for most things, but what if I have a collection within a collection? For example, List[List[Int]] (assuming that there exists some implementation of DataCollectionSerializer[List] and DataSerializer[Int]) would require an implementation of DataSerializer[List[Int]]. I could simply continue writing a new trait for each level of containment, however that would eventually result in some upper limit for what my Typeclass could achieve.
Is there some way that I could combine these two traits, to allow DataCollectionSerializer to operate upon any collection, providing its contents have either a DataSerializer or DataCollectionSerializer?
You can change DataCollectionSerializer to
trait DataCollectionSerializer[Collection[_]] {
def serializer[A: DataSerializer]: DataSerializer[Collection[A]]
}
and to get DataSerializer for e.g. List[Int]: implicitly[DataCollectionSerializer[List]].serializer[Int]. Then all non-higher-kind types have a DataSerializer and you don't need to mix anything.

Scala code generation with annotations + macros or external script?

I want to know:
Can Scala annotations/transforms implement the code generation below? (objective)
What are the trade-offs as opposed to source code generation with an external tool? (objective)
Is there a better way / how would you do it? (subjective)
Background:
I'm designing an embedded database for Scala + Java as a side project. Although I want it to be usable from Java, I'm writing it in Scala for the extra flexibility/power and because writing Java code kills my soul.
I'm working out what I want model definitions to look like. My initial idea was to parse some model definition files and generate Scala classes. But I think now I'd like them to be definable in Scala code so that no parsing is required and people can bring the full power of Scala to bear in defining and customizing the models (e.g. custom column types.) That's a valuable feature from my Python/Django experience.
So far I have something like:
#model
class Person {
val Name = StringColumn(length=32)
val BirthDate = DateColumn(optional=true)
}
#model
class Student extends Person {
val GPA = FloatColumn(propertyName="gpa")
}
#model
class Teacher extends Person {
val salary = NumericColumn()
}
Which would generate:
class Person {
val Name = StringColumn(name="name", length=32)
val BirthDate = DateColumn(name="birthDate", optional=true)
// generated accessor methods
def name = Person.Name.get(...)
def name_= (name : String) : Unit = Person.Name.set(..., name)
// etc ...
}
// static access to model metadata, e.g. Person.Name is an immutable StringColumn instance
object Person extends Person
class Student extends Person {
val GPA = DoubleColumn(name = "GPA")
def gpa = ...
def gpa_= (value : Float) = ...
}
object Student extends Student
class Teacher extends Person {
// You get the idea
}
object Teacher extends Teacher
Looking at some examples online and doing some research, it seems like AST transforms using a special #model annotation could actually generate the needed code, maybe with a little bit of help, e.g. having the user define the object as well with the model definition. Am I right that this can be done?
Some problems that occur to me with this idea:
The object will be cluttered with properties that are not useful, all it needs are the Column objects. This could be fixed by splitting the class into two classes, PersonMeta and Person extends PersonMeta with Person object extending PersonMeta only.
IDEs will probably not pick up on the generated properties, causing them to underline them with wavy lines (eww...) and making it so auto-complete for property names won't work. The code would still be compile-time checked, so it's really just an IDE gotcha (Dynamic, no doubt, has the same problem.)
Code generation using a script is more IDE friendly, but it's hacky, probably more work, especially since you have to leave custom methods and things intact. It also requires a custom build step that you have to run whenever you change a model (which means you can forget to do it.) While the IDE might not help you with macro code generation (yet, anyway) the compiler will shout at you if you get things wrong. That makes me lean towards doing it with macros + annotation.
What do you think? I'm new to Scala, I kind of doubt I've hit on the best way to define models and generate implementations for them. How would you do it better?
It's possible yeah. Macros can be unpleasant to write and debug, but they do work.
Seems like you already have your solution there
Scala IDEs tend to handle macros correctly-ish (I mean, they have to, they're part of the language and used in some pretty fundamental libraries), so I wouldn't worry about that; if anything a macro is more ide-friendly than an external codegen step because a macro will stay in sync with a user's changes.
I'd see whether you can achieve what you want in vanilla scala before resorting to a macro. Remember that your class-like things don't necessarily have to be actual case classes; take a look at Shapeless generic records for an idea of how you can represent a well-typed "row" of named values from somewhere external. I think a system that could map a structure like those records to and from SQL might end up being more principled (that is, easier to reason about) than one based on "special" case classes.

Why people define class, trait, object inside another object in Scala?

Ok, I'll explain why I ask this question. I begin to read Lift 2.2 source code these days.
It's good if you happened to read lift source code before.
In Lift, I found that, define inner class and inner trait are very heavily used.
object Menu has 2 inner traits and 4 inner classes. object Loc has 18 inner classes, 5 inner traits, 7 inner objects.
There're tons of codes write like this. I wanna to know why the author write like this.
Is it because it's the author's
personal taste or a powerful use of
language feature?
Is there any trade-off for this kind
of usage?
Before 2.8, you had to choose between packages and objects. The problem with packages is that they cannot contain methods or vals on their own. So you have to put all those inside another object, which can get awkward. Observe:
object Encrypt {
private val magicConstant = 0x12345678
def encryptInt(i: Int) = i ^ magicConstant
class EncryptIterator(ii: Iterator[Int]) extends Iterator[Int] {
def hasNext = ii.hasNext
def next = encryptInt(ii.next)
}
}
Now you can import Encrypt._ and gain access to the method encryptInt as well as the class EncryptIterator. Handy!
In contrast,
package encrypt {
object Encrypt {
private[encrypt] val magicConstant = 0x12345678
def encryptInt(i: Int) = i ^ magicConstant
}
class EncryptIterator(ii: Iterator[Int]) extends Iterator[Int] {
def hasNext = ii.hasNext
def next = Encrypt.encryptInt(ii.next)
}
}
It's not a huge difference, but it makes the user import both encrypt._ and encrypt.Encrypt._ or have to keep writing Encrypt.encryptInt over and over. Why not just use an object instead, as in the first pattern? (There's really no performance penalty, since nested classes aren't actually Java inner classes under the hood; they're just regular classes as far as the JVM knows, but with fancy names that tell you that they're nested.)
In 2.8, you can have your cake and eat it too: call the thing a package object, and the compiler will rewrite the code for you so it actually looks like the second example under the hood (except the object Encrypt is actually called package internally), but behaves like the first example in terms of namespace--the vals and defs are right there without needing an extra import.
Thus, projects that were started pre-2.8 often use objects to enclose lots of stuff as if they were a package. Post-2.8, one of the main motivations has been removed. (But just to be clear, using an object still doesn't hurt; it's more that it's conceptually misleading than that it has a negative impact on performance or whatnot.)
(P.S. Please, please don't try to actually encrypt anything that way except as an example or a joke!)
Putting classes, traits and objects in an object is sometimes required when you want to use abstract type variables, see e.g. http://programming-scala.labs.oreilly.com/ch12.html#_parameterized_types_vs_abstract_types
It can be both. Among other things, an instance of an inner class/trait has access to the variables of its parent. Inner classes have to be created with a parent instance, which is an instance of the outer type.
In other cases, it's probably just a way of grouping closely related things, as in your object example. Note that the trait LocParam is sealed, which means that all subclasses have to be in the same compile unit/file.
sblundy has a decent answer. One thing to add is that only with Scala 2.8 do you have package objects which let you group similar things in a package namespace without making a completely separate object. For that reason I will be updating my Lift Modules proposal to use a package object instead of a simple object.

Why do compile-time generative techniques for structural typing prevent separate compilation?

I was reading (ok, skimming) Dubochet and Odersky's Compiling Structural Types on the JVM and was confused by the following claim:
Generative techniques create Java interfaces to stand in
for structural types on the JVM. The complexity of such
techniques lies in that all classes that are to be used as
structural types anywhere in the program must implement
the right interfaces. When this is done at compile time, it
prevents separate compilation.
(emphasis added)
Consider the autoclose example from the paper:
type Closeable = Any { def close(): Unit }
def autoclose(t: Closeable)(run: Closeable => Unit): Unit = {
try { run(t) }
finally { t.close }
}
Couldn't we generate an interface for the Closeable type as follows:
public interface AnonymousInterface1 {
public void close();
}
and transform our definition of autoclose to
// UPDATE: using a view bound here, so implicit conversion is applied on-demand
def autoclose[T <% AnonymousInterface1](t: T)(run: T => Unit): Unit = {
try { run(t) }
finally { t.close }
}
Then consider a call-site for autoclose:
val fis = new FileInputStream(new File("f.txt"))
autoclose(fis) { ... }
Since fis is a FileInputStream, which does not implement AnonymousInterface1, we need to generate a wrapper:
class FileInputStreamAnonymousInterface1Proxy(val self: FileInputStream)
extends AnonymousInterface1 {
def close() = self.close();
}
object FileInputStreamAnonymousInterface1Proxy {
implicit def fis2proxy(fis: FileInputStream): FileInputStreamAnonymousInterface1Proxy =
new FileInputStreamAnonymousInterface1Proxy(fis)
}
I must be missing something, but it's unclear to me what it is. Why would this approach prevent separate compilation?
As I recall from a discussion on the Scala-Inernals mailing list, the problem with this is object identity, which is preserved by the current approach to compiling, is lost when you wrap values.
Think about it. Consider class A
class A { def a1(i: Int): String = { ... }; def a2(s: String): Boolean = { ... }
Some place in the program, possibly in a separately compiled library, this structural type is used:
{ def a1(i: Int): String }
and elsewhere, this one is used:
{ def a2(s: String): Boolean }
How, apart from global analysis, is class A to be decorated with the interfaces necessary to allow it to be used where those far-flung structural types are specified?
If every possible structural type that a given class could conform to is used to generate an interface capturing that structural type, there's an explosion of such interfaces. Remember, that a structural type may mention more than one required member, so for a class with N public elements (vals or defs) all the possible subsets of those N are required, and that's the powerset of N whose cardinality is 2^N.
I actually use the implicit approach (using typeclasses) you describe in the Scala ARM library. Remember that this is a hand-coded solution to the problem.
The biggest issue here is implicit resolution. The compiler will not generate wrappers for you on the fly, you must do so ahead of time and make sure they are one the implicit scope. This means (for Scala-ARM) that we provide "common" wrapper for whatever resources we can, and fall back to reflection-based types when we can't find the appropriate wrapper. This gives the advantage of allowing the user to specify their own wrapper using normal implicit rules.
See: The Resource Type-trait and all of it's predefined wrappers.
Also, I blogged about this technique describing the implicit resolution magic in more detail: Monkey Patching, Duck Typing and Type Classes.
In any case, you probably don't want to hand-encode a type class everytime you use structural types. If you actually wanted the compiler to automatically create an interface and do the magic for you, it could get messy. Everytime you define a structural type, the compiler will have to create an interface for it (somewhere in the ether perhaps?). We now need to add namespaces for these things. Also, with every call the compiler will have to generate some kind of a wrapper-implementation class (again with the namespace issue). Finally, if we have two different methods with the same structural type that are compiled separately, we've just exploded the number of interfaces we require.
Not that the hurdle couldn't be overcome, but if you want to have structural typing with "direct" access for particular types the type-trait pattern seems to be your best bet today.