How to force a val in a class to be immutable in class using class type in OCaml - class

Let's say I have this :
class type point_t =
object
val x : int
method getx : int
method move : int -> unit
end;;
I can write a class like this and it will work :
class point : point_t =
object
val mutable x = 0
method getx = x
method move d = x <- x + d
end;;
Now suppose that I want to create a class type that would NOT allow a class to be defined with a mutable val x (I want x to be immutable). Is there a way to do that ?

It is not possible, so if you don't want to allow implementations to use a mutable variable it is better just to hide it all and expose functional getter/setter:
class type point_t = object(self)
method get_x : int
method with_x : int -> self
method move : int -> self
end;;
You may omit with_x method if you want to allow updates only via the move method.
The reasoning for this is that a class with a mutable version of a variable is a proper subclass of a class with immutable version of the same variable, as it has the same set of operations, plus one more - an ability to set the variable. So, any abstraction over a type point_t can be applied to a class instance with and without a mutability (although it will not be able to mutate the variable). Note, that the opposite is not possible, if you will define the class type point_t with a mutable x, and will try to implement it with an immutable one, then the type system will complain. As your implementation doesn't provide all the operations.
Also, there is one thing that you possibly miss. Although, the class point has a mutable variable x this mutability is actually sealed (i.e., hidden) by the type constraint point_t. So, no matter what is the implementation, the interface is strictly defined to have immutable x:
class the_point = object
inherit point
method! move d = x <- x - d
end
method! move d = x <- x - d
^^^^^^^^^^
Error: The instance variable x is not mutable
Your confusion may arise from the fact that you have some experience with Java/C++ style of OOP, where class types are nominal, and a class can became a subclass of another class only by explicit inheritance. In OCaml a class is a subclass of another class if it is a syntactical superset of it, i.e., if it has at least all fields of the super class. There is no need to inherit from a super class, to become its subclass. And class point : point_t is not an inheritance, but a type constraint, that says: here is the class expression, that implements point_t class (and maybe more), please, make sure that it is true and expose only point_t interface to the outsiders.
And a final note, I've specifically denoted term sub classing as the syntactic super set of a super class to emphasize the fact that inheritance and sub classing do not imply subtyping. The latter is the semantics (i.e., the behavior of an instance), the former is syntax, i.e., a set of code fragments. Subclassing gives you a code reuse, the ability to copy the code from superclasses (as inherit is actually just copy/pasting the code of super class to your sub class). The subtyping gives you the polymorphism - an ability to use the same abstraction on different implementations.

Related

Using a Lens on a non-case class extending something with a constructor in Scala

I am probably thinking about this the wrong way, but I am having trouble in Scala to use lenses on classes extending something with a constructor.
class A(c: Config) extends B(c) {
val x: String = doSomeProcessing(c, y) // y comes from B
}
I am trying to create a Lens to mutate this class, but am having trouble doing so. Here is what I would like to be able to do:
val l = Lens(
get = (_: A).x,
set = (c: A, xx: String) => c.copy(x = xx) // doesn't work because not a case class
)
I think it all boils down to finding a good way to mutate this class.
What are my options to achieve something like that? I was thinking about this in 2 ways:
Move the initialization logic into a companion A object into a def apply(c: Config), and change the A class to be a case class that gets created from the companion object. Unfortunately I can't extend from B(c) in my object because I only have access to c in its apply method.
Make x a var. Then in the Lens.set just A.clone then set the value of x then return the cloned instance. This would probably work but seems pretty ugly, not to mention changing this to a var might raise a few eyebrows.
Use some reflection magic to do the copy. Not really a fan of this approach if I can avoid it.
What do you think? Am I thinking about this really the wrong way, or is there an easy solution to this problem?
This depends on what you expect your Lens to do. A Lens laws specify that the setter should replace the value that the getter would get, while keeping everything else unchanged. It is unclear what is meant by everything else here.
Do you wish to have the constructor for B called when setting? Do you which the doSomeProcessing method called?
If all your methods are purely functional, then you may consider that the class A has two "fields", c: Config and x: String, so you might as well replace it with a case class with those fields. However, this will cause a problem while trying to implement the constructor with only c as parameter.
What I would consider is doing the following:
class A(val c: Config) extends B(c) {
val x = doSomeProcessing(c, y)
def copy(newX: String) = new A(c) { override val x = newX }
}
The Lens you wrote is now perfectly valid (except for the named parameter in the copy method).
Be careful if you have other properties in A which depend on x, this might create an instance with unexpected values for these.
If you do not wish c to be a property of class A, then you won't be able to clone it, or to rebuild an instance without giving a Config to your builder, which Lenses builder cannot have, so it seems your goal would be unachievable.

scala's type checker doesn't recognize types in abstract path-dependent classes scenario

Let's define a trait with an abstract class
object Outer {
trait X {
type T
val empty: T
}
Now we can make an instance of it:
val x = new X {
type T = Int
val empty = 42
}
Scala now recognizes, that x.empty is an Int:
def xEmptyIsInt = x.empty: Int
Now, let's define an other class
case class Y(x: X) extends X {
type T = x.T
val empty = x.empty
}
and make an instance of it
val y = Y(x)
But now Scala, isn't able to infer that y.empty is of type Int. The following
def yEmptyIsInt = y.empty: Int
now produces an error message:
error: type mismatch;
found : y.x.T
required: Int
y.empty : Int
Why is this the case? Is this a scala bug?
We can mitigate this issue by introducing a parameters to the case class:
case class Z[U](x: X { type T = U }) extends X {
type T = U
val empty = x.empty
}
Then it works again
val z = Z(x)
def zEmptyIsInt: Int = z.empty
But we always have to mention all the types inside X at call-site. This ideally should be an implementation detail which leads to the following approach:
case class A[U <: X](z: U) extends X {
type T = z.T
val empty = z.empty
}
This also mitigates the issue
val a = A(x)
def aEmptyIsInt: Int = a.empty
}
So, to summarize, my questions are the following: Why does the simple case doesn't work? Is this a valid workaround? What other problems might come up when we follow one of the two workaround approaches? Is there a better approach?
You've re-used x for different things, so from here on I'll call the object instantiated by val x "instance x" and the x: X used in class Y "parameter x".
"Instance x" is an anonymous subclass of trait X with concrete members overriding trait X's abstract members. As a subclass of X you can pass it to the constructor for case class Y and it will be accepted happily, since as a subclass it is an X.
It seems to me you expect that case class Y will then check at runtime to see if the instance of X it is passed has overridden X's members, and generate an instance of Y whose members have different types depending on what was passed in.
This is emphatically not how Scala works, and would pretty much defeat the purpose of its (static) type system. For example, you wouldn't be able to do anything useful with Y.empty without runtime reflection since it could have any type at all, and at that point you're better off just using a dynamic type system. If you want the benefits of parametricity, free theorems, not needing reflection, etc. then you have to stick to statically determined types (with a small exception for pattern matching). And that's what Scala does here.
What actually happens is that you've told Y's constructor that parameter x is an X, and so the compiler statically determines that x.empty, has the type of X.empty, which is abstract type T. Scala's inference isn't failing; your types are actually mismatched.
Separately, this doesn't really have anything to do with path-dependent types. Here is a good walkthrough, but in short, path-dependent types are bound to their parent's instance, not determined dynamically at runtime.

Scala class that handles enumerations generically

I want to create a generic class that holds the value of an enumeration, and also allows access to the possible values of the enumeration. Think of a property editor for example - you need to know the current value of the property, and you also need to be able to know what other values are legal for the property. And the type of enumeration should not be known in advance, you should be able to work with any kind of enumeration.
My first thought was something like this:
class EnumerationProperty[T <: Enumeration](value:T)
However, that doesn't work because for enumerations T isn't a type, it's an object. Other variations I have tried are:
class EnumerationProperty[T <: Enumeration](value:T.Value)
class EnumerationProperty[T <: Enumeration.Value](value:T)
(I won't go into the details of why these don't work because I suspect the reasons aren't interesting.)
For first part of your question. You can define holder for generic enum value like this:
case class EnumerationProperty[T <: Enumeration#Value](value:T)
But I don't know how to get all enum values without explicitly pass Enumeration object. Enumeration has values() method to get all values. And Enumeration#Value has link to Enumeration, but with private access
In your use case (a property editor) I think the best solution is to rely on scala reflection available in scala 2.10. Given a class's TypeTag, you can get the full type (without erasure) of all of its members plus their values, and from that populate your property editor. For enumerations, use the TypeTag to get their values using the following method:
Using Scala 2.10 reflection how can I list the values of Enumeration?
Now, maybe you don't want or can't use scala reflection, and from now on I'll suppose this is the case. If that is true then you are opening a whole can of worm :)
TL;DR: This is not possible using a standard Enumeration, so you'll probably have to explcitly wrap the enumeration values as shown in Ptharien's Flame's answer (or roll your own fork of Enumeration). Below I detail all my attempts, please bear with me.
Unfortunately, and for some unknown reason to me (though I suspect it has to do with serialization issues), Enumeration.Value has no field pointing to its Enumeration instance. Given how Enumeration is implemented, this would be trivial to implement, but of course wehave no say, short of forking Enumeration and modifying our version (which is actually what I did for this very purpose, plus to add proper support for serialization and reflection - but I diggress).
If we can't modify Enumeration, maybe we can just extend it? Looking at the implementation again, something like this would seem to work:
class EnumerationEx extends Enumeration {
protected class ValEx(i: Int, name: String) extends Val(i, name) {
#transient val enum: Enumeration = EnumerationEx.this
}
override protected def Value(i: Int, name: String): Value = new ValEx(i, name)
}
object Colors extends EnumerationEx {
val Red, Green, Blue = Value
}
The downside would be that it only works for enumerations that explicitly extend EnumerationEx instead of Enumeration, but it would be better than nothing.
Unfortunately, this does not compile simply because def Value ... is declared final in Enumeration so there is no way to override it. (Note again that forking Enumeration would allow to circunvent this. Actually, why not do it, as we are already down the path of using a custom Enumeration anwyay. I'll let you judge).
So here is another take on it:
class EnumerationEx extends Enumeration {
class ValueWithEnum( inner: Value ) {
#transient val enum: Enumeration = EnumerationEx.this
}
implicit def valueToValue( value: Value ): ValueWithEnum = new ValueWithEnum( value )
}
And indeed it works as expected. Or so it seems.
scala> object Colors extends EnumerationEx {
| val Red, Green, Blue = Value
| }
defined module Colors
scala> val red = Colors.Red
red: Colors.Value = Red
scala> red.enum.values
res58: Enumeration#ValueSet = Colors.ValueSet(Red, Green, Blue)
Hooray? Well no, because the conversion from Value to ValueWithEnum is done only when accessing red.enum, not at the time of instantiation of the Colors enumeration. In other words, when calling enum the compiler needs to know the exact static type of the enumeration (the compiler must statically know that red's type is Colors.Value, and not just Enumeration# Value). And in the use case you mention (a property editor) you can only rely to java reflection (I already assumed that you won't use scala reflection) to get the type of an enumeration value, and java reflection will only give you Enumeration#Val (which extends Enumeration#Value) as the type of Colors.Red. So basically you are stuck here.
Your best bet is definitly to use scala reflection in the first place.
class EnumProps[E <: Enumeration](val e: E)(init: e.Value) {...}
Then you can use e and e.Value to implement the class.

Scala class constructor local parameters

Can I pass arguments to Scala class constructor that are not stored into class itself?
I want to achieve functionality which in Java could be written as follows:
class A {
private final SomethingElse y;
public A(Something x) {
y = x.derive(this);
}
}
I.e. class constructor takes parameter that is later transformed to another value using reference to this. The parameter is forgotten after constructor returns.
In Scala I can do:
class A(x: Something) {
val y = x.derive(this)
}
But it means that x is stored in the class, which I want to avoid. Since x.derive method uses reference to this, I can not make the transformation in companion object.
But it means that x is stored in the class, which I want to avoid.
If you don't reference constructor argument anywhere except the constructor itself, field won't be created. If you reference x e.g. in toString(), Scala will automatically create and assign private val for you.
Use javap -c -private A to verify what kind of fields are actually created.
BTW you pass this inside a constructor, which means a.derive() gets a reference to possibly non-initialized instance of A. Be careful!

Implement equality outside type definition

I have several types that implement an interface. Equality for these types only depends on interface members. Is it possible to define equality for these types once, without overriding Equals or op_Equality for each type?
EDIT
I tried the following, but, for whatever reason, it overrode every use of =, even for types not implementing IEntity.
[<AutoOpen>]
module Equality =
let inline op_Equality (left:IEntity) (right:IEntity) = true
I also tried using flexible types (#IEntity). Same result.
What you're trying to do is something that mixins or typeclasses might enable in other languages; unfortunately there isn't equivalent functionality in F#. Your best bet is probably one of the following options:
Use an abstract base class instead of an interface.
Write your equality method outside of your type and then have all of your implementations defer to it. For example,
let entityEquals (i1:IEntity) (i2:IEntity) =
i1.Member1 = i2.Member1 &&
i1.Member2 = i2.Member2 &&
...
type MyEntity() =
interface IEntity with
member x.Member1 = ...
...
override x.Equals(y) =
match y with
| :? IEntity as y -> entityEquals x y
| _ -> false
override x.GetHashCode() =
...
In addition to a bit of boilerplate, the downside here is that if anyone else implements your IEntity interface, they aren't forced to use your equality method - it's opt-in.
Create an another operator which you use for equality testing of IEntitys:
let (==) (i1:IEntity) (i2:IEntity) =
i1.Member1 = i2.Member1 &&
...
The (huge) downside of this is that structural equality of types containing IEntitys (such as tuples, records, etc.) won't use this operator to compare those components, which is likely to lead to surprising broken code.
I don't think there is a way to do this in a static way. The problem is that extension members (e.g. if you added op_Equality as an extension) are ignored by static member constraints (e.g. if you also redefined = using inlin with op_Equality requirement).
The F# compiler has some special powers available only when compiling FSharp.Core.dll that could help (search sources for the declaration let inline GenericOne). It uses something like static type switch - but this cannot be accessed by mere mortals.
So, I don't have any idea better than using dynamic type test, which isn't really a good approach and it's probably better to define a custom operator for comparison of your interfaces.
For a reference, the ugly dynamic approach would be:
let inline (=) a b =
match a, b with
| :? IFoo as a, :? IFoo as b -> yourEquals a b
| _ -> a = b