• Nenhum resultado encontrado

7.3. OBJECT-ORIENTED MECHANISMS

let keyword

ˆ Logical abbreviations whose bodies are formulae; they are introduced by the logical let keyword

ˆ Logical methods whose bodies are proofs (from Figure 7.11); they are introduced by the theorem keyword

ˆ The representation method whose body is a type (from Figure 7.1); each species contains exactly one representation; it is introduced by the representation keyword.

Here is an example of a species denition where all the proofs are assumed to shorten the example:

open " basics ";;

species PlusInteger = representation = int ;

let plus (x : Self, y : Self) : Self = x + y;

theorem plus_associative :

all x : Self, all y : Self, all z : Self, plus (x, plus (y, z)) = plus ( plus (x, y), z) proof = assumed ;

theorem plus_commute :

all x : Self, all y : Self, plus (x, y) = plus (y, x) proof = assumed ;

end;;

7.3.3 Inheritance

To avoid code duplication, FoCaLiZe oers the possibility to dene species by inheriting from one or several other species.

For example, we can extend the PlusInteger species by a neutral element:

species ZeroPlusInteger = inherit PlusInteger ; let zero : Self = 0;

theorem plus_zero : all x : Self, plus (x, zero ) = x proof = assumed ;

end;;

Multiple inheritance is allowed, when a dened method is present in several parent species, the ambiguity is syntactically solved by taking the denition of the rightmost

7.3. OBJECT-ORIENTED MECHANISMS

dening parent in the inherit clause.

7.3.4 Undened methods

Providing denitions for methods is not mandatory. An undened computational method can be introduced by the keyword signature and an undened logical method can be introduced by the keyword property; undened in this case means that the logical method has no proof yet. As there must be exactly one representation (dened or not) per species, no keyword is required for an undened representation.

Undened methods can be used to dene species representing algebraic structures.

For example, we can prove the unicity of the neutral element of any abelian group and instantiate this theorem in the special case of ZeroPlusInteger:

species AbelianGroup =

signature plus : Self -> Self -> Self; signature zero : Self;

signature opp : Self -> Self; property plus_associative :

all x : Self, all y : Self, all z : Self, plus (x, plus (y, z)) = plus ( plus (x, y), z);

property plus_commute :

all x : Self, all y : Self, plus (x, y) = plus (y, x);

property plus_zero : all x : Self, plus (x, zero ) = x;

property opp_plus : all x : Self, plus (x, opp (x)) = zero ; theorem zero_uniq :

all z : Self, (all x : Self, plus (x, z) = x) -> z = zero proof = assumed ;

end;;

species OppZeroPlus = inherit ZeroPlusInteger ;

let opp (x : Self) : Self = 0 - x;

theorem opp_plus : all x : Self, plus (x, opp (x)) = zero proof = assumed ;

end;;

species OppZeroPlusAbelian =

inherit OppZeroPlus , AbelianGroup ; end;;

All the methods of species OppZeroPlusAbelian are dened (we say that OppZeroPlusAbelian is a complete species) and the proof of zero_uniq does not depend on the choice of the type for the representation and can be used in any abelian group.

7.3. OBJECT-ORIENTED MECHANISMS

In this gure, frames represent species and there is an arrow from a species A to a speciesB ifA directly inherits from B.

Figure 7.14: Inheritance Hierarchy

In the course of a typical FoCaLiZe development, the rst species are totally abstract and the latter species rene them until all the methods are dened. The inheritance hierarchy of this example is pictured in Figure 7.14.

Species look a lot like typeclasses as found in Haskell, Coq and Isabelle. The main dierence which gives a real OO avor to FoCaLiZe species is redenition.

7.3.5 Redenition

When a dened computational method is inherited, it is possible to give it a new denition overriding the inherited one. As usual in object-oriented languages, the semantics of redenition is given by early binding: when a method gets several denitions it is bound to the last one, if a methodm1 refers to method m2 and m2 get redened, the meaning of m1 silently changes to refer to the new denition ofm2.

When a method is redened, proofs of logical methods depending on the previous denition via denition of facts are then not valid anymore and are removed in the child species, turning these logical methods to undened.

7.3. OBJECT-ORIENTED MECHANISMS

A typical example of the use of redenition is to provide default denitions that can then be replaced by more ecient ones when more properties are assumed. From an ordering relation, equality can be dened by antisymmetry:

species Setoid =

signature eq : Self -> Self -> bool;

property eq_refl : all x : Self, eq(x, x);

property eq_symm : all x y : Self, eq(x, y) -> eq(y, x);

property eq_trans :

all x y z : Self, eq(x, y) -> eq(y, z) -> eq(x, z);

end;;

species Ordering = inherit Setoid ;

signature leq : Self -> Self -> bool;

property leq_refl : all x : Self, leq (x, x);

property leq_trans :

all x y z : Self, leq (x, y) -> leq (y, z) -> leq (x, z);

let eq(x, y) = leq (x, y) && leq (y, x);

proof of eq_refl = by definition of eq property leq_refl ; proof of eq_symm = by definition of eq;

proof of eq_trans = by definition of eq property leq_trans ; end;;

type nat = | O | S( nat );;

species OrderedNat = inherit Ordering ; representation = nat ; let rec leq (x, y) =

match x with

| O -> true

| S(x) ->

(match y with

| O -> false

| S(y) -> leq (x, y ));

end;;

species EfficientOrderedNat = inherit OrderedNat ;

let rec eq(x, y) = match (x, y) with

| (O, O) -> true

| (O, S(_)) -> false

| (S(_), O) -> false

| (S(x), S(y)) -> eq(x, y);

7.3. OBJECT-ORIENTED MECHANISMS

end;;

In this example, the theorems on equality eq_refl,eq_symm, and eq_trans are proved in species OrderedNat but their proofs are erased in species EfficientOrderedNat because they depend on the denition of eq found in species OrderedNat which is unavailable in speciesEfficientOrderedNatand its descendents due to early binding.

7.3.6 Collections

Complete species can be transformed into collections on which methods can be called from the outside.

collection C =

implement OppZeroPlusAbelian ; end;;

The construction operation also abstracts the representation so C!zero_uniq proves the formula all z : C, (all x : C, plus(x, z) = x) -> z = zero and the type C is abstract, it can only be manipulated by the methods of the collection.

7.3.7 Parameters

Species can be parameterized. Two kinds of parameters are allowed:

ˆ is-parameters: if S is a previously dened species, parameterization over collections instantiating species inheriting from S is allowed with the syntax P is S

ˆ in-parameters: if C is a collection, paramerization over elements of C is allowed with the syntax p in C

For example, given two abelian groups G1 and G2, we can build the product of G1 and G2 which is also an abelian group:

species AbelianProduct (G1 is AbelianGroup , G2 is AbelianGroup ) = inherit AbelianGroup ;

representation = G1 * G2;

let zero = (G1!zero , G2! zero );