GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#############################################################################
##
## CAP package
##
## Copyright 2013, Sebastian Gutsche, TU Kaiserslautern
## Sebastian Posur, RWTH Aachen
##
##
#############################################################################
DeclareRepresentation( "IsCapCategoryAsCatObjectRep",
IsCapCategoryObjectRep and IsCapCategoryAsCatObject,
[ ] );
BindGlobal( "TheTypeOfCapCategoriesAsCatObjects",
NewType( TheFamilyOfCapCategoryObjects,
IsCapCategoryAsCatObjectRep ) );
DeclareRepresentation( "IsCapFunctorRep",
IsCapCategoryMorphismRep and IsCapFunctor,
[ ] );
BindGlobal( "TheTypeOfCapFunctors",
NewType( TheFamilyOfCapCategoryMorphisms,
IsCapFunctorRep ) );
DeclareRepresentation( "IsCapNaturalTransformationRep",
IsCapCategoryTwoCellRep and IsCapNaturalTransformation,
[ ] );
BindGlobal( "TheTypeOfCapNaturalTransformations",
NewType( TheFamilyOfCapCategoryTwoCells,
IsCapNaturalTransformationRep ) );
##
InstallGlobalFunction( CAP_INTERNAL_CREATE_Cat,
function( )
InstallValue( CapCat, rec( caching_info := rec( ) ) );
CREATE_CAP_CATEGORY_OBJECT( CapCat, [ [ "Name", "Cat" ] ] );
CREATE_CAP_CATEGORY_FILTERS( CapCat );
return CapCat;
end );
CAP_INTERNAL_CREATE_Cat( );
##
InstallMethod( AsCatObject,
[ IsCapCategory ],
function( category )
local cat_obj;
cat_obj := rec( );
ObjectifyWithAttributes( cat_obj, TheTypeOfCapCategoriesAsCatObjects,
AsCapCategory, category );
Add( CapCat, cat_obj );
SetIsWellDefined( cat_obj, true );
return cat_obj;
end );
BindGlobal( "CAP_INTERNAL_NICE_FUNCTOR_INPUT_LIST",
function( list )
local i;
for i in [ 1 .. Length( list ) ] do
if IsCapCategory( list[ i ] ) then
list[ i ] := [ list[ i ], false ]; ##true means opposite
elif IsCapCategoryAsCatObject( list[ i ] ) then
list[ i ] := [ AsCapCategory( list[ i ] ), false ];
elif IsList( list[ i ] ) and Length( list[ i ] ) = 2 and IsCapCategory( list[ i ][ 1 ] ) then
list[ i ][ 2 ] := true;
elif IsList( list[ i ] ) and Length( list[ i ] ) = 2 and IsCapCategoryAsCatObject( list[ i ][ 1 ] ) then
list[ i ] := [ AsCapCategory( list[ i ][ 1 ] ), true ];
fi;
od;
return list;
end );
BindGlobal( "CAP_INTERNAL_CREATE_FUNCTOR_SOURCE",
function( list )
local source_list, i;
source_list := [ ];
for i in list do
if i[ 2 ] = false then
Add( source_list, i[ 1 ] );
else
Add( source_list, Opposite( i[ 1 ] ) );
fi;
od;
return CallFuncList( Product, source_list );
end );
##
InstallMethod( CapFunctor,
[ IsString, IsList, IsCapCategory ],
function( name, source_list, range )
local source, functor;
functor := rec( );
source_list := CAP_INTERNAL_NICE_FUNCTOR_INPUT_LIST( source_list );
functor.input_source_list := source_list;
functor.number_arguments := Length( source_list );
source := CAP_INTERNAL_CREATE_FUNCTOR_SOURCE( source_list );
ObjectifyWithAttributes( functor, TheTypeOfCapFunctors,
Name, name,
Source, AsCatObject( source ),
Range, AsCatObject( range ) );
Add( CapCat, functor );
return functor;
end );
##
InstallMethod( CapFunctor,
[ IsString, IsCapCategory, IsCapCategory ],
function( name, source, range )
return CapFunctor( name, [ source ], range );
end );
##
InstallMethod( CapFunctor,
[ IsString, IsCapCategoryAsCatObject, IsCapCategory ],
function( name, source, range )
return CapFunctor( name, [ source ], range );
end );
##
InstallMethod( CapFunctor,
[ IsString, IsCapCategory, IsCapCategoryAsCatObject ],
function( name, source, range )
return CapFunctor( name, [ source ], AsCapCategory( range ) );
end );
##
InstallMethod( CapFunctor,
[ IsString, IsCapCategoryAsCatObject, IsCapCategoryAsCatObject ],
function( name, source, range )
return CapFunctor( name, [ source ], AsCapCategory( range ) );
end );
BindGlobal( "CAP_INTERNAL_SANITIZE_FUNC_LIST_FOR_FUNCTORS",
function( list )
local sanitized_list, i;
sanitized_list := [ ];
for i in list do
if IsFunction( i ) then
Add( sanitized_list, [ i, [ ] ] );
elif IsList( i ) and Length( i ) = 1 then
Add( sanitized_list, [ i[ 1 ], [ ] ] );
elif IsList( i ) and Length( i ) = 2 then
Add( sanitized_list, i );
else
Error( "wrong function input" );
fi;
od;
return sanitized_list;
end );
BindGlobal( "CAP_INTERNAL_FUNCTOR_CREATE_FILTER_LIST",
function( functor, type )
local filter_list;
filter_list := List( functor!.input_source_list, i -> i[ 1 ] );
if type = "cell" then
filter_list := List( filter_list, CellFilter );
elif type = "object" then
filter_list := List( filter_list, ObjectFilter );
elif type = "morphism" then
filter_list := List( filter_list, MorphismFilter );
elif type = "twocell" then
filter_list := List( filter_list, TwoCellFilter );
else
## Should never be reached
Error( "unrecognized type" );
fi;
return filter_list;
end );
BindGlobal( "CAP_INTERNAL_INSTALL_FUNCTOR_OPERATION",
function( operation, func_list, filter_list, cache )
local current_filter_list, current_method;
for current_method in func_list do
current_filter_list := CAP_INTERNAL_MERGE_FILTER_LISTS( filter_list, current_method[ 2 ] );
InstallMethodWithCache( operation, current_filter_list, current_method[ 1 ] : Cache := cache );
od;
end );
InstallMethod( FunctorObjectOperation,
[ IsCapFunctor ],
function( functor )
local filter_list;
filter_list := CAP_INTERNAL_FUNCTOR_CREATE_FILTER_LIST( functor, "object" );
return NewOperation( Concatenation( "CAP_FUNCTOR_", Name( functor ), "_OBJECT_OPERATION" ), filter_list );
end );
InstallMethod( FunctorMorphismOperation,
[ IsCapFunctor ],
function( functor )
local filter_list, range_cat;
filter_list := CAP_INTERNAL_FUNCTOR_CREATE_FILTER_LIST( functor, "morphism" );
range_cat := AsCapCategory( Range( functor ) );
filter_list := Concatenation( [ ObjectFilter( range_cat ) ], filter_list, [ ObjectFilter( range_cat ) ] );
return NewOperation( Concatenation( "CAP_FUNCTOR_", Name( functor ), "_MORPHISM_OPERATION" ), filter_list );
end );
##
InstallMethod( AddObjectFunction,
[ IsCapFunctor, IsList ],
function( functor, func_list )
local sanitized_list, filter_list, operation;
sanitized_list := CAP_INTERNAL_SANITIZE_FUNC_LIST_FOR_FUNCTORS( func_list );
filter_list := CAP_INTERNAL_FUNCTOR_CREATE_FILTER_LIST( functor, "object" );
if not IsBound( functor!.object_function_list ) then
functor!.object_function_list := sanitized_list;
else
Append( functor!.object_function_list, sanitized_list );
fi;
operation := FunctorObjectOperation( functor );
CAP_INTERNAL_INSTALL_FUNCTOR_OPERATION( operation, sanitized_list, filter_list, ObjectCache( functor ) );
end );
##
InstallMethod( AddObjectFunction,
[ IsCapFunctor, IsFunction ],
function( functor, func )
AddObjectFunction( functor, [ [ func, [ ] ] ] );
end );
##
InstallMethod( AddMorphismFunction,
[ IsCapFunctor, IsList ],
function( functor, func_list )
local sanitized_list, filter_list, operation, range_cat;
sanitized_list := CAP_INTERNAL_SANITIZE_FUNC_LIST_FOR_FUNCTORS( func_list );
filter_list := CAP_INTERNAL_FUNCTOR_CREATE_FILTER_LIST( functor, "morphism" );
range_cat := AsCapCategory( Range( functor ) );
filter_list := Concatenation( [ ObjectFilter( range_cat ) ], filter_list, [ ObjectFilter( range_cat ) ] );
if not IsBound( functor!.morphism_function_list ) then
functor!.morphism_function_list := sanitized_list;
else
Append( functor!.morphism_function_list, sanitized_list );
fi;
operation := FunctorMorphismOperation( functor );
CAP_INTERNAL_INSTALL_FUNCTOR_OPERATION( operation, sanitized_list, filter_list, MorphismCache( functor ) );
end );
##
InstallMethod( AddMorphismFunction,
[ IsCapFunctor, IsFunction ],
function( functor, func )
AddMorphismFunction( functor, [ [ func, [ ] ] ] );
end );
##
InstallMethod( ObjectCache,
[ IsCapFunctor ],
function( functor )
return CachingObject( functor!.number_arguments );
end );
##
InstallMethod( MorphismCache,
[ IsCapFunctor ],
function( functor )
return CachingObject( functor!.number_arguments + 2 );
end );
##
InstallGlobalFunction( ApplyFunctor,
function( arg )
local functor, arguments, is_object, cache, cache_return, computed_value,
source_list, source_value, range_list, range_value, i, tmp;
functor := arg[ 1 ];
arguments := arg{[ 2 .. Length( arg ) ]};
if Length( arguments ) = 1 and functor!.number_arguments > 1 then
arguments := Components( arguments[ 1 ] );
for i in [ 1 .. Length( arguments ) ] do
if functor!.input_source_list[ i ][ 2 ] = true then
arguments[ i ] := Opposite( arguments[ i ] );
fi;
od;
elif Length( arguments ) = 1 and functor!.input_source_list[ 1 ][ 2 ] = true and
IsIdenticalObj( CapCategory( arguments[ 1 ] ), Opposite( functor!.input_source_list[ 1 ][ 1 ] ) ) then
arguments[ 1 ] := Opposite( arguments[ 1 ] );
fi;
if IsCapCategoryObject( arguments[ 1 ] ) then
computed_value := CallFuncList( FunctorObjectOperation( functor ), arguments );
elif IsCapCategoryMorphism( arguments[ 1 ] ) then
source_list := List( arguments, Source );
range_list := List( arguments, Range );
for i in [ 1 .. Length( arguments ) ] do
if functor!.input_source_list[ i ][ 2 ] = true then
tmp := source_list[ i ];
source_list[ i ] := range_list[ i ];
range_list[ i ] := source_list[ i ];
fi;
od;
source_value := CallFuncList( ApplyFunctor, Concatenation( [ functor ], source_list ) );
range_value := CallFuncList( ApplyFunctor, Concatenation( [ functor ], range_list ) );
computed_value := CallFuncList( FunctorMorphismOperation( functor ), Concatenation( [ source_value ], arguments, [ range_value ] ) );
else
Error( "Second argument of ApplyFunctor must be a category cell" );
fi;
Add( AsCapCategory( Range( functor ) ), computed_value );
return computed_value;
end );
##
AddPreCompose( CapCat,
function( left_functor, right_functor )
local new_functor;
new_functor := CapFunctor( Concatenation( "Composition of ",
Name( left_functor ),
" and ",
Name( right_functor ) ),
AsCapCategory( Source( left_functor ) ),
AsCapCategory( Range( right_functor ) ) );
AddObjectFunction( new_functor,
obj -> ApplyFunctor( right_functor, ApplyFunctor( left_functor, obj ) )
);
AddMorphismFunction( new_functor,
function( new_source, morphism, new_range )
return ApplyFunctor( right_functor, ApplyFunctor( left_functor, morphism ) );
end );
return new_functor;
end );
##
AddIdentityMorphism( CapCat,
function( category )
local new_functor;
new_functor := CapFunctor( Concatenation( "Identity functor of ", Name( AsCapCategory( category ) ) ),
category, category );
AddObjectFunction( new_functor,
IdFunc );
AddMorphismFunction( new_functor,
function( arg ) return arg[ 2 ]; end );
return new_functor;
end );
##
AddTerminalObject( CapCat,
function( )
return CAP_INTERNAL_TERMINAL_CATEGORY_AS_CAT_OBJECT;
end );
##
AddUniversalMorphismIntoTerminalObject( CapCat,
function( category )
local new_functor;
new_functor := CapFunctor( Concatenation( "The terminal of ", Name( AsCapCategory( category ) ) ), category, CAP_INTERNAL_TERMINAL_CATEGORY_AS_CAT_OBJECT );
AddObjectFunction( new_functor,
function( arg ) return UniqueObject( CAP_INTERNAL_TERMINAL_CATEGORY ); end );
AddMorphismFunction( new_functor,
function( arg ) return UniqueMorphism( CAP_INTERNAL_TERMINAL_CATEGORY ); end );
return new_functor;
end );
##
AddUniversalMorphismIntoTerminalObjectWithGivenTerminalObject( CapCat,
function( category, cat_obj )
local new_functor;
new_functor := CapFunctor( Concatenation( "The terminal of ", Name( AsCapCategory( category ) ) ), category, CAP_INTERNAL_TERMINAL_CATEGORY_AS_CAT_OBJECT );
AddObjectFunction( new_functor,
function( arg ) return UniqueObject( CAP_INTERNAL_TERMINAL_CATEGORY ); end );
AddMorphismFunction( new_functor,
function( arg ) return UniqueMorphism( CAP_INTERNAL_TERMINAL_CATEGORY ); end );
return new_functor;
end );
##
AddDirectProduct( CapCat,
function( product_of_categories )
return AsCatObject( CallFuncList( Product, List( Components( product_of_categories ), AsCapCategory ) ) );
end );
##
AddProjectionInFactorOfDirectProductWithGivenDirectProduct( CapCat,
function( object_product_list, direct_product, projection_number )
local projection_functor;
projection_functor := CapFunctor(
Concatenation( "Projection into ", String( projection_number ),"-th factor of ", Name( AsCapCategory( direct_product ) ) ),
direct_product,
object_product_list[ projection_number ]
);
AddObjectFunction( projection_functor,
function( obj )
return obj[ projection_number ];
end );
AddMorphismFunction( projection_functor,
function( new_source, morphism, new_range )
return morphism[ projection_number ];
end );
return projection_functor;
end );
##
AddUniversalMorphismIntoDirectProductWithGivenDirectProduct( CapCat,
function( diagram, sink, direct_product )
local name_string, universal_functor;
name_string := Concatenation(
"Product functor from ",
Name( AsCapCategory( Source( sink[1] ) ) ),
" to ",
Name( AsCapCategory( direct_product ) )
);
universal_functor := CapFunctor( name_string, Source( sink[1] ), direct_product );
AddObjectFunction( universal_functor,
function( object )
local object_list;
object_list := List( Components( sink ), F -> ApplyFunctor( F, object ) );
return CallFuncList( Product, object_list );
end );
AddMorphismFunction( universal_functor,
function( new_source, morphism, new_range )
local morphism_list;
morphism_list := List( Components( sink ), F -> ApplyFunctor( F, morphism ) );
return CallFuncList( Product, morphism_list );
end );
return universal_functor;
end );
####################################
##
## Functor convinience
##
####################################
InstallMethod( InstallFunctor,
[ IsCapFunctor, IsString ],
function( functor, install_name )
local object_name, morphism_name, object_filters, object_product_filters, morphism_filters,
morphism_product_filters, current_filters, install_list;
if IsBound( functor!.is_already_installed ) then
return;
fi;
if IsBoundGlobal( install_name ) and not IsOperation( ValueGlobal( install_name ) ) then
Error( Concatenation( "cannot install functor under name ", install_name ) );
fi;
object_name := Concatenation( install_name, "OnObjects" );
if HasObjectFunctionName( functor ) then
object_name := ObjectFunctionName( functor );
fi;
if IsBoundGlobal( object_name ) and not IsOperation( ValueGlobal( object_name ) ) then
Error( Concatenation( "cannot install functor object function under name ", object_name ) );
fi;
SetObjectFunctionName( functor, object_name );
morphism_name := Concatenation( install_name, "OnMorphisms" );
if HasMorphismFunctionName( functor ) then
object_name := MorphismFunctionName( functor );
fi;
if IsBoundGlobal( morphism_name ) and not IsOperation( ValueGlobal( morphism_name ) ) then
Error( Concatenation( "cannot install functor morphism function under name ", morphism_name ) );
fi;
SetObjectFunctionName( functor, morphism_name );
object_filters := CAP_INTERNAL_FUNCTOR_CREATE_FILTER_LIST( functor, "object" );
morphism_filters := CAP_INTERNAL_FUNCTOR_CREATE_FILTER_LIST( functor, "morphism" );
object_product_filters := [ ObjectFilter( AsCapCategory( Source( functor ) ) ) ];
morphism_product_filters := [ MorphismFilter( AsCapCategory( Source( functor ) ) ) ];
install_list := [
[ install_name, object_filters ],
[ install_name, morphism_filters ],
[ object_name, object_filters ],
[ morphism_name, morphism_filters ]
];
if object_filters <> object_product_filters then
Append( install_list, [ [ install_name, object_product_filters ], [ object_name, object_product_filters ] ] );
fi;
if morphism_filters <> morphism_product_filters then
Append( install_list, [ [ install_name, morphism_product_filters ], [ morphism_name, morphism_product_filters ] ] );
fi;
for current_filters in install_list do
CallFuncList( DeclareOperation, current_filters );
InstallMethod( ValueGlobal( current_filters[ 1 ] ),
current_filters[ 2 ],
function( arg )
return CallFuncList( ApplyFunctor, Concatenation( [ functor ], arg ) );
end );
od;
functor!.is_already_installed := true;
end );
##
InstallMethod( IdentityFunctor,
[ IsCapCategory ],
function( category )
return IdentityMorphism( AsCatObject( category ) );
end );
##
InstallMethod( FunctorCanonicalizeZeroObjects,
[ IsCapCategory ],
function( category )
local CZ, zero_obj;
if not CanCompute( category, "IsZeroForObjects" ) then
Error( "the category cannot compute IsZeroForObjects\n" );
fi;
CZ := CapFunctor( "functor canonicalizing zero objects", category, category );
zero_obj := ZeroObject( category );
AddObjectFunction( CZ,
function( obj )
if IsZero( obj ) then
return zero_obj;
fi;
return obj;
end );
AddMorphismFunction( CZ,
function( new_source, mor, new_range )
if IsZero( Source( mor ) ) then
return UniversalMorphismFromZeroObjectWithGivenZeroObject( new_range, new_source );
elif IsZero( Range( mor ) ) then
return UniversalMorphismIntoZeroObjectWithGivenZeroObject( new_source, new_range );
fi;
return mor;
end );
return CZ;
end );
##
InstallMethod( NaturalIsomorophismFromIdentityToCanonicalizeZeroObjects,
[ IsCapCategory ],
function( category )
local Id, F, iso;
Id := IdentityFunctor( category );
F := FunctorCanonicalizeZeroObjects( category );
iso := NaturalTransformation(
Concatenation( "natural isomorphism from the identity functor to ", Name( F ) ),
Id, F );
AddNaturalTransformationFunction(
iso,
function( source, obj, range )
if IsZero( range ) then
return UniversalMorphismIntoZeroObjectWithGivenZeroObject( source, range );
fi;
return IdentityMorphism( obj );
end );
SetIsIsomorphism( iso, true );
return iso;
end );
##
InstallMethod( FunctorCanonicalizeZeroMorphisms,
[ IsCapCategory ],
function( category )
local CZ;
if not CanCompute( category, "IsZeroForMorphisms" ) then
Error( "the category cannot compute IsZeroForMorphisms\n" );
fi;
CZ := CapFunctor( "functor canonicalizing zero morphisms", category, category );
AddObjectFunction( CZ, IdFunc );
AddMorphismFunction( CZ,
function( new_source, mor, new_range )
if IsZero( mor ) then
return ZeroMorphism( new_source, new_range );
fi;
return mor;
end );
return CZ;
end );
##
InstallMethod( NaturalIsomorophismFromIdentityToCanonicalizeZeroMorphisms,
[ IsCapCategory ],
function( category )
local Id, F, iso;
Id := IdentityFunctor( category );
F := FunctorCanonicalizeZeroMorphisms( category );
iso := NaturalTransformation(
Concatenation( "natural isomorphism from the identity functor to ", Name( F ) ),
Id, F );
AddNaturalTransformationFunction(
iso,
function( source, obj, range )
return IdentityMorphism( obj );
end );
SetIsIsomorphism( iso, true );
return iso;
end );
###################################
##
## Natural transformations
##
###################################
##
InstallMethod( NaturalTransformation,
[ IsCapFunctor, IsCapFunctor ],
function( source, range )
return NaturalTransformation( Concatenation( "A Natural transformation from ", Name( source ), " to ", Name( range ) ), source, range );
end );
##
InstallMethod( NaturalTransformation,
[ IsString, IsCapFunctor, IsCapFunctor ],
function( name, source, range )
local natural_transformation;
##formally, this has to be IsEqualForObjects (of CAT), but
##equality of categories is given by IsIdenticalObj.
if not IsIdenticalObj( Source( source ), Source( range ) ) or not IsIdenticalObj( Range( source ), Range( range ) ) then
Error( "a natural transformation between these functors does not exist" );
fi;
natural_transformation := rec( );
ObjectifyWithAttributes( natural_transformation, TheTypeOfCapNaturalTransformations,
Name, name,
Source, source,
Range, range );
Add( CapCategory( source ), natural_transformation );
return natural_transformation;
end );
##
InstallMethod( NaturalTransformationCache,
[ IsCapNaturalTransformation ],
function( natural_trafo )
return CachingObject( Source( natural_trafo )!.number_arguments + 2 );
end );
##
InstallMethod( NaturalTransformationOperation,
[ IsCapNaturalTransformation ],
function( trafo )
local filter_list;
filter_list := CAP_INTERNAL_FUNCTOR_CREATE_FILTER_LIST( Source( trafo ), "object" );
filter_list := Concatenation( [ ObjectFilter( AsCapCategory( Range( Source( trafo ) ) ) ) ], filter_list, [ ObjectFilter( AsCapCategory( Range( Source( trafo ) ) ) ) ] );
return NewOperation( Concatenation( "CAP_NATURAL_TRANSFORMATION_", Name( trafo ), "_OPERATION" ), filter_list );
end );
##
InstallMethod( AddNaturalTransformationFunction,
[ IsCapNaturalTransformation, IsList ],
function( trafo, func_list )
local sanitized_list, filter_list, operation, range_cat;
sanitized_list := CAP_INTERNAL_SANITIZE_FUNC_LIST_FOR_FUNCTORS( func_list );
filter_list := CAP_INTERNAL_FUNCTOR_CREATE_FILTER_LIST( Source( trafo ), "object" );
filter_list := Concatenation( [ ObjectFilter( AsCapCategory( Range( Source( trafo ) ) ) ) ], filter_list, [ ObjectFilter( AsCapCategory( Range( Source( trafo ) ) ) ) ] );
if not IsBound( trafo!.function_list ) then
trafo!.function_list := sanitized_list;
else
Append( trafo!.function_list, sanitized_list );
fi;
operation := NaturalTransformationOperation( trafo );
CAP_INTERNAL_INSTALL_FUNCTOR_OPERATION( operation, sanitized_list, filter_list, NaturalTransformationCache( trafo ) );
end );
##
InstallMethod( AddNaturalTransformationFunction,
[ IsCapNaturalTransformation, IsFunction ],
function( trafo, func )
AddNaturalTransformationFunction( trafo, [ [ func, [ ] ] ] );
end );
InstallGlobalFunction( ApplyNaturalTransformation,
function( arg )
local trafo, source_functor, arguments, i, source_value, range_value, computed_value;
trafo := arg[ 1 ];
source_functor := Source( trafo );
arguments := arg{[ 2 .. Length( arg ) ]};
if Length( arguments ) = 1 and source_functor!.number_arguments > 1 then
arguments := Components( arguments[ 1 ] );
for i in [ 1 .. Length( arguments ) ] do
if source_functor!.input_source_list[ i ][ 2 ] = true then
arguments[ i ] := Opposite( arguments[ i ] );
fi;
od;
elif Length( arguments ) = 1 and source_functor!.input_source_list[ 1 ][ 2 ] = true and
IsIdenticalObj( CapCategory( arguments[ 1 ] ), Opposite( source_functor!.input_source_list[ 1 ][ 1 ] ) ) then
arguments[ 1 ] := Opposite( arguments[ 1 ] );
fi;
source_value := CallFuncList( ApplyFunctor, Concatenation( [ source_functor ], arguments ) );
range_value := CallFuncList( ApplyFunctor, Concatenation( [ Range( trafo ) ], arguments ) );
computed_value := CallFuncList( NaturalTransformationOperation( trafo ), Concatenation( [ source_value ], arguments, [ range_value ] ) );
Add( AsCapCategory( Range( source_functor ) ), computed_value );
## TODO: this should be replaced by an "a => b" todo_list with more properties
if HasIsIsomorphism( trafo ) and IsIsomorphism( trafo ) then
SetIsIsomorphism( computed_value, true );
fi;
return computed_value;
end );
InstallMethod( InstallNaturalTransformation,
[ IsCapNaturalTransformation, IsString ],
function( trafo, install_name )
local object_filters, object_product_filters, current_filters;
if IsBound( trafo!.is_already_installed ) then
return;
fi;
if IsBoundGlobal( install_name ) and not IsOperation( ValueGlobal( install_name ) ) then
Error( Concatenation( "cannot install natural transformation under name ", install_name ) );
fi;
object_filters := CAP_INTERNAL_FUNCTOR_CREATE_FILTER_LIST( Source( trafo ), "object" );
object_product_filters := [ ObjectFilter( AsCapCategory( Source( Source( trafo ) ) ) ) ];
for current_filters in [
[ install_name, object_filters ],
[ install_name, object_product_filters ],
] do
CallFuncList( DeclareOperation, current_filters );
InstallMethod( ValueGlobal( current_filters[ 1 ] ),
current_filters[ 2 ],
function( arg )
return CallFuncList( ApplyNaturalTransformation, Concatenation( [ trafo ], arg ) );
end );
od;
trafo!.is_already_installed := true;
end );
##
AddVerticalPreCompose( CapCat,
function( above_transformation, below_transformation )
local new_natural_transformation;
new_natural_transformation := NaturalTransformation( Concatenation( "Vertical composition of ",
Name( above_transformation ),
" and ",
Name( below_transformation ) ),
Source( above_transformation ),
Range( below_transformation ) );
AddNaturalTransformationFunction( new_natural_transformation,
function( source_value, object, range_value )
return PreCompose( ApplyNaturalTransformation( above_transformation, object ),
ApplyNaturalTransformation( below_transformation, object ) );
end );
return new_natural_transformation;
end );
##
InstallMethodWithCacheFromObject( HorizontalPreComposeNaturalTransformationWithFunctor,
[ IsCapNaturalTransformation, IsCapFunctor ],
function( natural_transformation, functor )
local composition;
composition := NaturalTransformation( Concatenation( "Horizontal composition of natural transformation ",
Name( natural_transformation ),
" and functor ",
Name( functor ) ),
PreCompose( Source( natural_transformation ), functor ),
PreCompose( Range( natural_transformation ), functor ) );
AddNaturalTransformationFunction( composition,
function( source_value, object, range_value )
return ApplyFunctor( functor, ApplyNaturalTransformation( natural_transformation, object ) );
end );
return composition;
end );
##
InstallMethodWithCacheFromObject( HorizontalPreComposeFunctorWithNaturalTransformation,
[ IsCapFunctor, IsCapNaturalTransformation ],
function( functor, natural_transformation )
local composition;
composition := NaturalTransformation( Concatenation( "Horizontal composition of functor ",
Name( functor ),
" and natural transformation ",
Name( natural_transformation ) ),
PreCompose( functor, Source( natural_transformation ) ),
PreCompose( functor, Range( natural_transformation ) ) );
AddNaturalTransformationFunction( composition,
function( source_value, object, range_value )
return ApplyNaturalTransformation( natural_transformation, ApplyFunctor( functor, object ) );
end );
return composition;
end );
##
AddHorizontalPreCompose( CapCat,
function( left_natural_transformation, right_natural_transformation )
local pre_compose_transfo_functor, pre_compose_functor_transfo;
pre_compose_transfo_functor :=
HorizontalPreComposeNaturalTransformationWithFunctor( left_natural_transformation, Source( right_natural_transformation ) );
pre_compose_functor_transfo :=
HorizontalPreComposeFunctorWithNaturalTransformation( Range( left_natural_transformation ), right_natural_transformation );
return VerticalPreCompose( pre_compose_transfo_functor, pre_compose_functor_transfo );
end );
###################################
##
## IsWellDefined
##
###################################
AddIsWellDefinedForObjects( CapCat,
IsCapCategoryAsCatObjectRep
);
Finalize( CapCat );