OCL define invariant - invariants

If I have to define an invariant to state that the age of a person requesting a loan should be greater than 18 for the attached class diagram would this be
context Person
inv: age > 18
or
context Person
inv: self.age > 18
and what is the difference between the two?
Thank you for your guidance

Both invariants in your example are exactly the same (the "self" is implicit in the first). Nevertheless, there you just say that all "person" objects must have an age value of at least 18 which is not exactly the invariant you described (in your invariant, it seemed that it was possible to have people under 18 in the system, it´s just that people under 18 could not be linked to a loan)

As Jordi already said they are semantically equivalent. The first includes the self implicitly.
As he mentioned either, your OCL invariant does not match the textual representation you gave us. In your invariant, people must be older than 18. However, the owner of the load should be greater than 18. So your invariant should be formulated on Loan.
context Loan
inv: owner.age > 18
which also has implicit self, so the second is semantically equivalent to the first one:
context Loan
inv: self.owner.age > 18

Related

UML Class Diagram - abstract or interface?

How can I know if class A is an interface, an abstract class or a concrete class (super class)?
According to answers, there are no direct instances of A so I assume that is an abstract class.
However, in this second image :
B should also be an abstract, if the first theory is right... but it can't because in the last answer there are direct instances of B class.
If A would be abstract in image1 it would be shown with the name in italics and/or the string {abstract} next to it. This is not the case here. Therefore A can have direct instances. I guess there is a mistake in image1.
Please note that even if B in image2 would be abstract, it is meaningful to specify an instance of B. An instance specification is not an instance, and as such can be incomplete and abstract. An object will have complete features and a concrete class. For example I could have a red Basketball. In the model I might have an instance specification classified by Ball{abstract} and without a slot for the color, because I don't care which type and color it is. So any instance of Basketball or Handball will fit this instance specification.
As per UML specification, Section 9.2.3.2:
The isAbstract property of Classifier, when true, specifies that the Classifier is abstract, i.e., has no direct instances: every instance of the abstract Classifier shall be an instance of one of its specializations.
The notation is described a bit further, in Section 9.2.4.1:
The name of an abstract Classifier is shown in italics, where permitted by the font in use. Alternatively or in addition, an abstract Classifier may be shown using the textual annotation {abstract} after or below its name.
Neither of the two is indicated in the first diagram, so the answer is simply erroneous.
Note, one more indirect indication of the abstract class (though it is not directly mentioned, just comes from the general description) could be using a Generalization Set. There are a couple of notations used here, you can read about them in Section 9.7.4 (the entire Section 9.7 is about Generalization Sets). This notation also isn't used so still - there is nothing to indicate class A is abstract.
First diagram
You cannot deduct from the diagram if A is an interface, an abstract class or a concrete class:
A could be a concrete class that is further specialized by B and C
A could be an abstract class and B and C be abstract or concrete specializations. One would expect A to be in italic or followed with an {abstract} adornment, but these are not mandatory.
A could even be an interface under some circumstances. In this case, B and C would be specialized interfaces. This possibility has however a low probability because the «interface» keyword would be expected above A. This notation was not mandatory in earlier UML 2 versions but the current UML 2.5 requires it (see Axel's comment).
So if the UML notation would be used with all possible accuracy, A would be a concrete class, but you can objectively not be 100% certain.
Important note: the provided answer claiming that "there is no instance for A" is hearsay. No element in the diagram allows to draw this conclusion
Second diagram
We have seen that the answers to the first questions are flawed, and likewise, B is not necessarily an abstract class.
Important revelation: you need to know that b : B is possible even if B was abstract, because in an object diagram you may chose arbitrarily to show membership to one class, event if the object would be more specialized:
UML 2.5 - Section 9.8.3: An InstanceSpecification represents the possible or actual existence of instances in a modeled system and completely or partially describes those instances.
In case of doubt, a few lines later, you'll read:
The InstanceSpecification may represent: - Classification of the instance by one or more Classifiers, any of which may be abstract.
Keeping this in mind, the answers to the second diagram are all correct, whether B is abstract or not.

Does Scala guarantee coherence in the presence of implicits?

The article Type classes: confluence, coherence and global uniqueness makes the following points -
[Coherence] states that every different valid typing derivation of a program leads to a resulting program that has the same dynamic semantics.
[..]
So, what is it that people often refer to when they compare Scala type classes to Haskell type classes? I am going to refer to this as global uniqueness of instances, defining to say: in a fully compiled program, for any type, there is at most one instance resolution for a given type class. Languages with local type class instances such as Scala generally do not have this property, but in Haskell, we find this property is a very convenient one when building abstractions like sets.
If you look at this paper on Modular implicits, it states -
[..] Scala’s coherence can rely on the weaker property of non-ambiguity
instead of canonicity. This means that you can define multiple implicit objects of type Showable[Int]
in your program without causing an error. Instead, Scala issues an error if the resolution of an implicit
parameter is ambiguous. For example, if two implicit objects of type Showable[Int] are in scope when
show is applied to an Int then the compiler will report an ambiguity error.
Both of these give the impression that Scala does ensure coherence but does not ensure global uniqueness of instances.
However, if you look at Martin Odersky's comments (1, 2), it seems that the term coherence is being used as shorthand for "uniqueness of instances", which would explain the terms "local coherence" and "global coherence".
Is this just an unfortunate case of the same term being used to mean two different things? They're certainly distinct -- OCaml's modular implicits ensure coherence (as per the first definition) but not global uniqueness of instances.
Does Scala guarantee coherence (as per the first definition) in the presence of implicits?
I think they mean the same thing in this case. Coherence is only put into question when you have more than one way of deriving the instance/implicit value; "every different valid typing derivation" is only interesting when there is more than once typing derivation. Both Scala and Haskell disallow at compile time instances which might lead to ambiguous derivations.
Scala
Odersky's comment says it for Scala: there is only ever one local way of resolving instances. In other words, there is only one valid local typing derivation. Trivially enough, it is coherent with itself. It isn't clear to me that it even makes sense to to talk about global coherence in Scala but, if it does, Scala definitely doesn't have it:
object Object1 {
implicit val i: Int = 9
println(implicitly[Int]) // valid typing derivation of `Int` => printing 9
}
object Object2 {
implicit val i: Int = 10
println(implicitly[Int]) // valid typing derivation of `Int` => printing 10
}
Haskell
Since Haskell instances are global, there is no point in distinguishing local/global coherence.
Haskell disallows at compile time having two instances where either instance head overlaps with the other. This turns finding type derivations into an unambiguous non-backtracking search problem. The non-ambiguity is again what gets us coherence.
Interestingly enough, GHC allows you to loosen this requirement with -XIncoherentInstances allowing you to write locally non-confluent instances, potentially breaking global coherence too.

Add duration to a moment using time4j

As I am converting code using the java.time implementation to time4j, I want to add a Duration to a Moment but I get a compilation error. Under java.time, I would do the following:
val startTime: ZonedDateTime = ...
val duration: TemporalAmount = ...
val endTime: ZonedDateTime = startTime.plus(duration)
Using time4j though, the same does not work:
val startTime: Moment = ...
val duration: Duration[ClockUnit] = ...
val endTime: Moment = startTime.plus(duration)
The compiler complains about the generics interaction between the Duration and the Moment. No matter which way I create a Duration (at least that I found), it would need to have an associated generic of java.util.concurrent.TimeUnit, because Moment implements TimePoint[java.util.concurrent.TimeUnit] and the Moment#plus method hence needs a Duration[java.util.concurrent.TimeUnit] with the same associated generic as Moment for the time unit.
This surprises me that java.util.concurrent.TimeUnit is used as this is not a time4j type. Am I missing the finer details around this choice? I have the impression that this was decided by design.
One way that works is if I use a PlainTimestamp and adds a Duration[ClockUnit | CalendarUnit | IsoUnit], as the former type implements TimePoint[IsoUnit, PlainTime] and overloads extra supported units. Then I can convert the PlainTimestamp to whatever timezone I need afterward. Is this the intended design?
(And still:) What's the proper Duration type to use with Moment.plus method?
I am using time4j version 4.27.2
Short answer how to migrate zonedDateTime.plus(Duration.ofHours(24)):
Moment.from(zonedDateTime.toInstant()).plus(MachineTime.of(24, TimeUnit.HOURS));
See also the API of the global duration type MachineTime.
Long answer in detail:
In contrast to the java.time-API which only knows only one single class ChronoUnit for representing the most used temporal units applicable on arbitrary temporal entities (and the general interface TemporalUnit), the unit and duration design of the library Time4J is much more fine-grained.
Every calendar or temporal type with a timeline has its own unit type which also characterizes the timeline of the temporal type in a distinct way so even the compiler will tell you not to mix up different unit types of different entities like Moment (counterpart to java.time.Instant) or PlainTimestamp (counterpart to LocalDateTime).
This distinction is coded by design as generic type parameter U in the super class TimePoint. For concrete classes: Moment works primarily with java.util.concurrent.TimeUnit while PlainTimestamp works with any implementation of IsoUnit, especially with the enums CalendarUnit and ClockUnit.
The generalized duration concept is described by the interface TimeSpan which is also specified by the unit type U to be used. You can only add a timespan to a moment if the unit type is java.util.concurrent.TimeUnit. This is offered by the special implementation class MachineTime. Furthermore, the other duration implementation, called net.time4j.Duration is only compatible with local types like PlainTimestamp.
Special temporal entities have their own sets of suitable units. For example, the unit for eras does only exist in the Japanese calendar but not for other calendars which have either zero, one or only two eras.
Why different unit types for Moment and PlainTimestamp?
Partially this is already answered by the last item about suitable sets of units. Example, months and years do not make much sense for machine-like types as Moment. Therefore the chosen enum java.util.concurrent.TimeUnit covers what is needed as units for Moment.
In addition, the different unit types of Time4J help to differentiate. A net.time4j.Duration<ClockUnit> is calculated in a local context while a MachineTime<TimeUnit> is calculated as global duration. This is not only true for clock-related units like hours but also for calendrical units. A year is not simply a year. We have ISO-calendar years (corresponding to gregorian years). We have ISO-week-based-years (length of 364 or 371 days). We have islamic years (354 or 355 days) and so on. Therefore Time4J knows a lot of different calendar units (watch out the API of the calendar-module). So Time4J finally adopted a design to prevent comparisons of durations with different unit types (which would be like comparing apples and oranges).
Following example for the rare case of changing the international dateline in Samoa (2011-12-30 was left out) demonstrates how important the distinction of unit types might be:
In Time4J, we just use different unit types to express if the arithmetic happens on the local or on the global timeline. Conclusion: In Java-8, we have to carefully study the context, in Time4J the unit types give valuable extra information.
ZonedDateTime zdt = ZonedDateTime.of(2011, 12, 29, 0, 0, 0, 0, "Pacific/Apia");
Moment m1 = Moment.from(zdt.toInstant());
Moment m2 = m1.plus(MachineTime.of(24, TimeUnit.HOURS));
assertThat(m2.isSimultaneous(m1.plus(MachineTime.of(1, TimeUnit.DAYS))), is(true));
System.out.println(m2); // 2011-12-30T10:00:00Z
System.out.println(m2.toZonalTimestamp(PACIFIC.APIA)); // 2011-12-31T00
System.out.println(m1.toZonalTimestamp(PACIFIC.APIA).plus(2, CalendarUnit.DAYS)); // 2011-12-31T00
The objects TimeUnit.DAYS and CalendarUnit.DAYS are obviously not the same. They require even different amounts (1 versus 2) to create the same results.
Side note:
I have now shortened the first version of my answer - mainly leaving out the Java-8-related stuff because I think it is easily possible to write too much about the topic of unit/duration-design in the narrow context of your question (and I have not even given any kind of complete answer). A tutorial page or extra documentation page like here on SO would indeed be a better place.
But at least two other points not mentioned in my answer might be interesting for you, too (concerns net.time4j.Duration): Sign handling and specialized timezone-metric. Last one can even be an alternative for MachineTime in some cases.

why FunctionN(0-22) ProductN(1-22) TupleN(1-22)?

The api has FunctionN(0-22) ProductN(1-22) TupleN(1-22)
the question is:
1.why the number is end of 22? why not 21 or 23?
2.why Function is start with 0 ? but Product and Tuple are not?
It does not make sense to have a Product or a Tuple that contains no elements. These would be equivalent to Unit.
Function0 exists because a function does not necessarily take arguments (e.g. in the case of by-name arguments).
In the case of Tuple22 and Function22 I cannot tell why the Scala team chose 22 as a maximum but it definitely is awkward to have tuples with that many members or functions that take more than 22 arguments.
It could be though that there is a restriction on how many arguments to a method the JVM can handle.

could someone explain the connection between type covariance/contravariance and category theory?

I am just starting to read about category theory, and would very much appreciate it if someone could explain the connection between CS contravariance/covariance and category theory. What would some example categories be (i.e. what are their objects/morphisms?)? Thanks in advance?
A contravariant functor from $C$ to $D$ is the exact same thing as a normal (i.e. covariant) functor from $C$ to $D^{op}$, where $D^{op}$ is the opposite category of $D$. So it's probably best to understand opposite categories first -- then you'll automatically understand contravariant functors!
Contravariant functors don't come up all that often in CS, although I can think of two exceptions:
You may have heard of contravariance in the context of subtyping. Although this is technically the same term, the connection is really, really weak. In object oriented programming, the classes form a partial order; every partial order is a category with "binary hom-sets" -- given any two objects $A$ and $B$, there is exactly one morphism $A\to B$ iff $A\leq B$ (note the direction; this slightly-confusing orientation is the standard for reasons I won't explain here) and no morphisms otherwise.
Parameterized types like, say, Scala's PartialFunction[-A,Unit] are functors from this simple category to itself... we usually focus on what they do to objects: given a class X, PartialFunction[X,Unit] is also a class. But functors preserve morphisms too; in this case if we had a subclass Dog of Animal, we would have a morphism Dog$\to$Animal, and the functor would preserve this morphism, giving us a morphism PartialFunction[Animal,Unit]$\to$PartialFunction[Dog,Unit], telling us that PartialFunction[Animal,Unit] is a subclass of PartialFunction[Dog,Unit]. If you think about that, it makes sense: suppose you have a situation where you need a function that works on Dogs. A function that works on all Animals would certainly work there!
That said, using full-on category theory to talk about partially ordered sets is big-time overkill.
Less common, but actually uses the category theory: consider the category Types(Hask) whose objects are the types of the Haskell programming language and where a morphism $\tau_1\to\tau_2$ is a function of type $\tau_1$->$\tau_2$. There is also a category Judgments(Hask) whose objects are lists of typing judgments $\tau_1\vdash\tau_2$ and whose morphisms are proofs of all the judgments on one list using the judgments on the other list as hypotheses. There is a functor from Types(Hask) to Judgments(Hask) which takes a Types(Hask)-morphism $f:A\to B$ to the proof
B |- Int
----------
......
----------
A |- Int
which is a morphism $(B\vdash Int)\to(A\vdash Int)$ -- notice the change of direction. Basically what this is saying is that if you've got a function that turns A's into B'a, and an expression of type Int with a free variable x of type B, then you can wrap it with "let x = f y in ..." and arrive at an expression still of type Int but whose only free variable is of type $A$, not $B$.
There are very nice videos about contravariance/covariance in Going deep channel in Microsoft Channel9. You can start here:
E2E: Brian Beckman and Erik Meijer - Co/Contravariance in Physics and Programming, 1 of 3
E2E: Brian Beckman and Erik Meijer - Co/Contravariance in Physics and Programming, 2 of 3
E2E: Brian Beckman and Erik Meijer - Co/Contravariance in Physics and Programming, 3 of n
E2E: Whiteboard Jam Session with Brian Beckman and Greg Meredith - Monads and Coordinate Systems