How do you do equational reasoning for user defined equational relations with agda-stdlib? - equality

agda-stdlib has facilities for doing equational reasoning for various specific library defined relations (example). It also has a type that identifies equality relations defined here. What is the easiest way for me to get access to the same facilities for equational reason I get with propositional equality.

The kit is defined in Relation.Binary.Reasoning.Setoid.
You only need to define a proof S that your relation defines a Setoid and then you can open import Relation.Binary.Reasoning.Setoid S to get the equational reasoning combinators.

Related

How does Scheme abstract data?

In statically typed language, people are able to use algebraic data type to abstract data and also generate constructors, or use class, trait and mixin to deal with data abstraction.
In dynamically typed language, like Python and Ruby, they all provide a class system to users.
But what about scheme, the simplest functional language, the closest one to λ-calculi, how does it abstract data?
Do scheme programmers usually just put data in a list or a lambda abstraction, and write some accessor function to make it look like a tree or something else? like EOPL says: specifying data via interfaces.
And then how does this abstraction technique relate to abstract data type (ADT) and objects? with regard to On understanding data abstraction, revisited.
What SICP (and I guess, EOPL) is advocating is just using functions to access data; then you can always switch one set of functions for another, implementing the same named set of functions to work with another concrete implementation. And that (i.e. the sets of such functions) is what forms the "interfaces", and that's what you put in different source files, and by just loading the appropriate one you can switch the concrete implementation while all the other code is none the wiser. That's what makes it "abstract" datatype.
As for the algebraic data types, the old bare-bones Scheme way is to create closures (that hold and hide the data) which respond to "messages" and thus become "objects" (something about "Scheme mailboxes"). This gives us products, i.e. records, and functions we get for free from Scheme itself. For sum types, just as in C/C++, we can use tagged unions in a disciplined manner (or, again, hide the specifics behind a set of "interface" functions).
EOPL has something called "variant-case" which handles such sum types in a manner similar to pattern matching. Searching brings up e.g. this link saying
I'm using DrScheme w/ the EOPL textbook, which uses define-record and variant-​case. I've got the macro definitions from the PLT site, but am now dealing with ...
so seems relevant, as one example.

How can we have an Association that is not an Aggregation?

Aggregation is defined as a special case of association. However, any association that is not implemented as a field (like having a relationship through method parameters) are being described as "use" relationship.
So, is it possible to have an association that is not aggregation or composition? If yes, I need a code example for such a case, please.
In fact, I'd say that most cases of associations in models are neither aggregations nor compositions (both are forms of part-whole relationship types). For instance, the association between the classes Publisherand Book for assigning the books published by a publisher to this publisher is neither an aggregation nor a composition because the books published by a publisher are not parts or components of this publisher.
For implementing this bidirectional association, we use the two mutually inverse reference properties Publisher::publishedBooks and Book::publisher, as shown in the following class rectangles:
Notice that the multi-valued reference property Publisher::publishedBooks is normally implemented by a list-valued property in Java.
I have explained how to use associations and reference properties in design models in my tutorial Managing Unidirectional Associations in a JavaScript Frontend Web App.
Shared aggregation (empty diamond) is not defined strictly in the UML standard. So, it is not easy to find a situation, where you can not use it.
But it is explicitely forbidden to use it for both sides of association. So, if you have relation many to many, you have to show it on class diagram as many to many association with none aggregation. Of course, you can show it as TWO shared association, but it is not our target, is it? :-)
As for code, if people visit many courses and courses are visited by many people, make a list "courses" for Person class and a list "visitors" for Course class.
Of course, on the other side, you always can use none instead of shared for any shared association, it is at your wish and up to rules of your place of work. But I don't know these rules, sorry :-). But surely, nobody will make you to use aggregation for 1 to 1 association.

What does Include & Extend correspond to in Programming?

Just as Generalization in UML corresponds to Inheritance, what do Include & Extend relationships correspond to in OOP?
I do realize that Generalization represents a 'is-a' relationship. Would Include represent 'has-a' relationship?
There are no include or extend relationships in UML Class Diagrams. If you refer to Use Case Diagrams they have no direct representation on code level, as you do not implement a Use Case as a single artifact in your software.
AFAIK, include used in Use Case diagrams. It shows dependency between specific use case and common use case.
Example:
Ask question on StackOverflow ----include----> Login to StackOverflow
Includes means direct dependency, which means that an including use case requires an including use case. Extension means extra functionality that you can add to a use case at a specified point.
An example of include relation is when you include a class in java. You must have the class for your code to execute, but this doesn't mean that you always call the other class.
An example of extends are eclipse extension points, which let you define new functionality for the eclipse platform at specified points, but the platform is unaware of the extensions.

How can type classes be used to implement persistence, introspection, identity, printing,

In the discussion on The Myths of Object-Orientation, Tim Sweeney describes what he thinks is a good alternative to the all-encompassing frameworks that we all use today.
He seems most interested in typeclasses:
we can use constructs like typeclasses to define features (like persistence, introspection,
identity, printing) orthogonally to type constructs like classes and
interfaces
I am passingly familiar with type classes as "types of types" but I am not sure exactly how they would be applied to the fore-mentioned problems: persistence, printing, ...
Any ideas?
My best guess would be code reuse through default methods and orthogonal definition through detachment of type class implementation from type itself.
Basically, when you define type class, you can define default implementations for methods. For example Eq (equality) class in Haskell defines /= (not equal) as not (x == y) and this method will work by default for all implementation of the type class. In a similar way in other language you could define a type class with all persistence code written (Save, Load) except for one or two methods. Or, in a language with good reflection capabilities you could define all persistence methods in advance. In practice, it is kind of similar to multiple inheritance.
Now, the other thing is that you do not have to attach the type class to your type in the same place where you define your type, you can actually do it later and in a different place. This allows persistence logic to be nicely separated from the original type.
Some good examples in how that looks like in an OOP language are in my favorite paper ever: http://www.stefanwehr.de/publications/Wehr_JavaGI_generalized_interfaces_for_Java.pdf. Their description of default implementations and retroactive interface implementations are essentially the same language features as I have just described.
Disclaimer: I do not really know Haskell so I might be wrong in places

Why avoid subtyping?

I have seen many people in the Scala community advise on avoiding subtyping "like a plague". What are the various reasons against the use of subtyping? What are the alternatives?
Types determine the granularity of composition, i.e. of extensibility.
For example, an interface, e.g. Comparable, that combines (thus conflates) equality and relational operators. Thus it is impossible to compose on just one of the equality or relational interface.
In general, the substitution principle of inheritance is undecidable. Russell's paradox implies that any set that is extensible (i.e. does not enumerate the type of every possible member or subtype), can include itself, i.e. is a subtype of itself. But in order to identify (decide) what is a subtype and not itself, the invariants of itself must be completely enumerated, thus it is no longer extensible. This is the paradox that subtyped extensibility makes inheritance undecidable. This paradox must exist, else knowledge would be static and thus knowledge formation wouldn't exist.
Function composition is the surjective substitution of subtyping, because the input of a function can be substituted for its output, i.e. any where the output type is expected, the input type can be substituted, by wrapping it in the function call. But composition does not make the bijective contract of subtyping-- accessing the interface of the output of a function, does not access the input instance of the function.
Thus composition does not have to maintain the future (i.e. unbounded) invariants and thus can be both extensible and decidable. Subtyping can be MUCH more powerful where it is provably decidable, because it maintains this bijective contract, e.g. a function that sorts a immutable list of the supertype, can operate on the immutable list of the subtype.
So the conclusion is to enumerate all the invariants of each type (i.e. of its interfaces), make these types orthogonal (maximize granularity of composition), and then use function composition to accomplish extension where those invariants would not be orthogonal. Thus a subtype is appropriate only where it provably models the invariants of the supertype interface, and the additional interface(s) of the subtype are provably orthogonal to the invariants of the supertype interface. Thus the invariants of interfaces should be orthogonal.
Category theory provides rules for the model of the invariants of each subtype, i.e. of Functor, Applicative, and Monad, which preserve function composition on lifted types, i.e. see the aforementioned example of the power of subtyping for lists.
One reason is that equals() is very hard to get right when sub-typing is involved. See How to Write an Equality Method in Java. Specifically "Pitfall #4: Failing to define equals as an equivalence relation". In essence: to get equality right under sub-typing, you need a double dispatch.
I think the general context is for the lanaguage to be as "pure" as possible (ie using as much as possible pure functions), and comes from the comparison with Haskell.
From "Ruminations of a Programmer"
Scala, being a hybrid OO-FP language has to take care of issues like subtyping (which Haskell does not have).
As mentioned in this PSE answer:
no way to restrict a subtype so that it can't do more than the type it inherits from.
For example, if the base class is immutable and defines a pure method foo(...), derived classes must not be mutable or override foo() with a function that is not pure
But the actual recommendation would be to use the best solution adapted to the program you are currently developing.
Focusing on subtyping, ignoring the issues related to classes, inheritance, OOP, etc.. We have the idea subtyping represents a isa relation between types. For example, types A and B have different operations but if A isa B we then can use any of B's operations on an A.
OTOH, using another traditional relation, if C hasa B then we can reuse any of B's operations on a C. Usually languages let you write one with a nicer syntax, a.opOnB instead of a.super.opOnB as it would be in the case of composition, c.b.opOnB
The problem is that in many cases there's more than one way to relate two types. For example Real can be embedded in Complex assuming 0 on the imaginary part, but Complex can be embedded in Real by ignoring the imaginary part, so both can be seen as subtypes of the other and subtyping forces one relation to be viewed as preferred. Also, there are more possible relations (e.g. view Complex as a Real using theta component of polar representation).
In formal terminology we usually say morphism to such relations between types and there are special kinds of morphisms for relations with different properties (e.g. isomorphism, homomorphism).
In a language with subtyping usually there's much more sugar on isa relations and given many possible embeddings we tend to see unnecessary friction whenever we're using the unpreferred relation. If we bring inheritance, classes and OOP to the mix the problem becomes much more visible and messy.
My answer does not answer why it is avoided but tries to give another hint at why it can be avoided.
Using "type classes" you can add an abstraction over existing types/classes without modifying them. Inheritance is used to express that some classes are specializations of a more abstract class. But with type classes you can take any existing classes and express that they all share a common property, for example they are Comparable. And as long as you are not concerned with them being Comparable you don't even notice it. The classes don't inherit any methods from some abstract Comparable type as long as you don't use them. It's a bit like programming in dynamic languages.
Further reads:
http://blog.tmorris.net/the-power-of-type-classes-with-scala-implicit-defs/
http://debasishg.blogspot.com/2010/07/refactoring-into-scala-type-classes.html
I don't know Scala, but I think the mantra 'prefer composition over inheritance' applies for Scala exactly the way it does for every other OO programming language (and subtyping is often used with the same meaning as 'inheritance'). Here
Prefer composition over inheritance?
you will find some more information.
I think lots of Scala programmers are former Java programmers. They are used to think in term of Object Oriented subtyping and they should be able to easily find OO-like solution for most problems. But Functional Programing is a new paradigm to discover, so people ask for a different kind of solutions.
This is the best paper I have found on the subject. A motivating quote from the paper –
We argue that while some of the simpler aspects of object-oriented languages are
compatible with ML, adding a full-fledged class-based object system to ML leads to an excessively complex
type system and relatively little expressive gain