# ImmutableType -- the class of immutable types

## Description

All types are implemented as hash tables. Most types are mutable, so that additional methods for handling their instances can be added at any time. However, if a type has an ancestor where the methods can be stored, then mutability is not needed.

When a type is used to represent a mathematical object, then immutability is desirable, in order to make the strict equality operator work on it. For example, a module M is a type, with its elements are its instances, but we would like to be able to compare two modules quickly, and form sets of modules. This is possible, because we have implemented modules as immutable types, and we have put the methods for adding and subtracting elements of M into the class Vector.

 i1 : F = ZZ^3 3 o1 = ZZ o1 : ZZ-module, free i2 : class F o2 = Module o2 : Type i3 : parent class F o3 = ImmutableType o3 : Type i4 : showStructure class F o4 = Thing : HashTable : ImmutableType : Module o4 : Descent i5 : showStructure F o5 = Thing : BasicList : Vector : F o5 : Descent i6 : v = F_0 + 3*F_2 o6 = | 1 | | 0 | | 3 | 3 o6 : ZZ i7 : F === ZZ^3 o7 = true i8 : set (ZZ^3, ZZ^2, ZZ^3) 2 3 o8 = set {ZZ , ZZ } o8 : Set i9 : peek F o9 = Module of Vector{cache => CacheTable{...3...} } numgens => 3 RawFreeModule => free(rank 3 degrees = {1, 1, 1}) ring => ZZ
Another advantage of immutability of modules is that there is no particular reason, aside from efficiency, to avoid creating a given module multiple times, as one copy of the module is as good as another.
 i10 : ZZ^3_0 + ZZ^3_2 o10 = | 1 | | 0 | | 1 | 3 o10 : ZZ