The following functions deal with types or category names and general structures. Magma has two levels of granularity when referring to types. In most cases, the coarser grained types (of type Cat) are used. Examples of these kinds of types are "polynomial rings" (RngUPol) and "finite fields" (FldFin). However, sometimes more specific typing information is sometimes useful. For instance, the algorithm used to factorize polynomials differs significantly, depending on the coefficient ring. Hence, we might wish to implement a specialized factorization algorithm polynomials over some particular ring type. Due to this need, Magma also supports extended types.
An extended type (of type ECat) can be thought of as a type taking a parameter. Using extended types, we can talk about "polynomial rings over the integers" (RngUPol[RngInt]), or "maps from the integers to the rationals" (Map[RngInt, FldRat]). Extended types can interact with normal types in all ways, and thus generally only need to be used when the extra level of information is required.
Given any object x, return the type (or category name) of x.
Given any object x, return the extended type (or category name) of x.
Given types (or extended types) T and U, return whether T ISA U, i.e., whether objects of type T inherit properties of type U. For example, ISA(RngInt, Rng) is true, because the ring of integers Z is a ring.
Returns the underlying base type of the extended type T.
Returns the number of parametrizing objects for the extended type T.
The i-th parametrizing object of the extended type T. Although this will usually be another extended type, as the example below shows it may not be.
> Z := Integers(); > Zx<x> := PolynomialRing(Z); > S := [ x ]; > f1 := map<Zx -> Z | f :-> Evaluate(f, 1)>; > D := CremonaDatabase(); > > ExtendedType(Z); RngInt > ExtendedType(Zx); RngUPol[RngInt] > ExtendedType(S); SeqEnum[RngUPolElt[RngInt]] > ExtendedType(f1); Map[RngUPol[RngInt], RngInt] > ExtendedType(D); DB["CrvEll"]We can see a few points of note from the above. If the type is not parameterized at all, like Z, then the extended type prints as just the base type. The printing for S shows that extended types may themselves be further parameterized. The printing for f1 shows that there may be more than one parametrizing object. The printing for D shows that parametrizing objects are not necessarily extended types.
We can use further investigate these with the intrinsics BaseType, '#', and indexing.
> tS := ExtendedType(S); > BaseType(tS); SeqEnum > #tS; 1 > tS[1]; RngUPolElt[RngInt] > #tS[1]; 1 > tS[1][1]; RngInt > Type(tS[1][1]); ECat > > tD := ExtendedType(D); > BaseType(tD); DB > #tD; 1 > tD[1]; CrvEll > Type(tD[1]); MonStgEltThis information could be put together to generate a tree of the type information (represented as a list).
> function tree(t) > if Type(t) ne ECat then > return [* t *]; > end if; > return [* BaseType(t) *] cat [* $$(t[i]) : i in [1..#t] *]; > end function; > function type_tree(object) > return tree(ExtendedType(object)); > end function; > > type_tree(Z); [* RngInt *] > type_tree(Zx); [* RngUPol, [* RngInt *] *] > type_tree(S); [* SeqEnum, [* RngUPolElt, [* RngInt *] *] *] > type_tree(f1); [* Map, [* RngUPol, [* RngInt *] *], [* RngInt *] *] > type_tree(D); [* DB, [* CrvEll *] *]Remember that the "CrvEll" in the last tree is a string, not a type.
> Type($1[2][1]); MonStgElt
Given a string S specifying a type return the actual type corresponding to S. This is useful when some intrinsic name hides the symbol which normally refers to the actual type.
Given any structure S, return the type of the elements of S. For example, the element type of the ring of integers Z is RngIntElt since that is the type of the integers which lie in Z.
Given structures S and T, return a covering structure C for S and T, so that S and T both embed into C. An error results if no such covering structure exists.
Given structures S and T, return whether a covering structure C for S and T exists, and if so, return such a C, so that S and T both embed into C.
> Type(3);
RngIntElt
> t := MakeType("RngIntElt");
> t;
RngIntElt
> Type(3) eq t;
true
> Z := IntegerRing();
> Type(Z);
RngInt
> ElementType(Z);
RngIntElt
> ISA(RngIntElt, RngElt);
true
> ISA(RngIntElt, GrpElt);
false
> ISA(FldRat, Fld);
true
The following give examples of when covering structures exist or do not
exist.
> Q := RationalField(); > CoveringStructure(Z, Q); Rational Field > ExistsCoveringStructure(Z, DihedralGroup(3)); false > ExistsCoveringStructure(Z, CyclotomicField(5)); true Cyclotomic Field of order 5 and degree 4 > ExistsCoveringStructure(CyclotomicField(3), CyclotomicField(5)); true Cyclotomic Field of order 15 and degree 8 > ExistsCoveringStructure(GF(2), GF(3)); false > ExistsCoveringStructure(GF(2^6), GF(2, 15)); true Finite field of size 2^30Our last example demonstrates the use of extended types:
> R<x> := PolynomialRing(Integers()); > ExtendedType(R); RngUPol[RngInt] > ISA(RngUPol[RngInt], RngUPol); true > f := x + 1; > ExtendedType(f); RngUPolElt[RngInt] > ISA(RngUPolElt[RngInt], RngUPolElt); true