packages feed

moonlight-category-0.1.0.0: src-simplicial/Moonlight/Category/Pure/Simplicial/Presheaf.hs

-- | Simplicial sets as presheaves on the simplex category: object and morphism
-- maps with identity and composition law checks.
module Moonlight.Category.Pure.Simplicial.Presheaf
  ( SimplicialPresheaf,
    presheafUpperBound,
    presheafObjectMap,
    presheafMorphismMap,
    generatedAsPresheaf,
    applyPresheaf,
    presheafIdentityLaw,
    presheafCompositionLaw,
  )
where

import Control.Monad ((<=<), foldM)
import Data.Function ((&))
import Data.Kind (Type)
import Numeric.Natural (Natural)
import Moonlight.Category.Pure.Simplicial.Delta
  ( DeltaMorphism,
    composeDeltaMorphism,
    deltaIdentity,
    injectionMissingIndices,
    normalCodomainDimension,
    normalDomainDimension,
    normalInjection,
    normalSurjection,
    normalizeDeltaMorphism,
    surjectionDegeneracyIndices,
  )
import Moonlight.Category.Pure.Simplicial.Set
  ( GeneratedSSet,
    applyGeneratedDegeneracyAtDimension,
    applyGeneratedFaceAtDimension,
    generatedSimplicesAtDimension,
    generationBound,
  )

type SimplicialPresheaf :: Type -> Type
data SimplicialPresheaf simplex = SimplicialPresheaf
  { presheafUpperBound :: Natural,
    presheafObjectMap :: Natural -> [simplex],
    presheafMorphismMap :: DeltaMorphism -> simplex -> Maybe simplex
  }

applyPresheaf :: SimplicialPresheaf simplex -> DeltaMorphism -> simplex -> Maybe simplex
applyPresheaf = presheafMorphismMap

stepFaces :: (Natural -> Natural -> simplex -> Maybe simplex) -> Natural -> [Natural] -> simplex -> Maybe (Natural, simplex)
stepFaces applyFace startDimension faceIndices simplexValue =
  foldM
    ( \(dimensionValue, currentSimplex) faceIndex -> do
        nextSimplex <- applyFace dimensionValue faceIndex currentSimplex
        pure (dimensionValue - 1, nextSimplex)
    )
    (startDimension, simplexValue)
    (reverse faceIndices)

stepDegeneracies :: (Natural -> Natural -> simplex -> Maybe simplex) -> Natural -> [Natural] -> simplex -> Maybe (Natural, simplex)
stepDegeneracies applyDegeneracy startDimension degeneracyIndices simplexValue =
  foldM
    ( \(dimensionValue, currentSimplex) degeneracyIndex -> do
        nextSimplex <- applyDegeneracy dimensionValue degeneracyIndex currentSimplex
        pure (dimensionValue + 1, nextSimplex)
    )
    (startDimension, simplexValue)
    (reverse degeneracyIndices)

applyWithGenerators ::
  (Natural -> Natural -> simplex -> Maybe simplex) ->
  (Natural -> Natural -> simplex -> Maybe simplex) ->
  DeltaMorphism ->
  simplex ->
  Maybe simplex
applyWithGenerators applyFace applyDegeneracy morphism simplexValue =
  do
    normalForm <- normalizeDeltaMorphism morphism
    let missingFaces =
          injectionMissingIndices
            (normalCodomainDimension normalForm)
            (normalInjection normalForm)
        degeneracyIndices = surjectionDegeneracyIndices (normalSurjection normalForm)
    (middleDimension, afterFaces) <-
      stepFaces applyFace (normalCodomainDimension normalForm) missingFaces simplexValue
    (resultDimension, afterDegeneracies) <-
      stepDegeneracies applyDegeneracy middleDimension degeneracyIndices afterFaces
    if resultDimension == normalDomainDimension normalForm
      then Just afterDegeneracies
      else Nothing

generatedAsPresheaf :: GeneratedSSet simplex -> SimplicialPresheaf simplex
generatedAsPresheaf generatedSet =
  SimplicialPresheaf
    { presheafUpperBound = generationBound generatedSet,
      presheafObjectMap = generatedSimplicesAtDimension generatedSet,
      presheafMorphismMap =
        applyWithGenerators
          (applyGeneratedFaceAtDimension generatedSet)
          (applyGeneratedDegeneracyAtDimension generatedSet)
    }

presheafIdentityLaw :: Eq simplex => SimplicialPresheaf simplex -> Natural -> Bool
presheafIdentityLaw presheaf dimensionValue =
  presheafObjectMap presheaf dimensionValue
    & all
      (\simplexValue -> applyPresheaf presheaf (deltaIdentity dimensionValue) simplexValue == Just simplexValue)

presheafCompositionLaw ::
  Eq simplex =>
  SimplicialPresheaf simplex ->
  DeltaMorphism ->
  DeltaMorphism ->
  simplex ->
  Bool
presheafCompositionLaw presheaf outer inner simplexValue =
  let leftAction =
        composeDeltaMorphism outer inner
          >>= (\composed -> applyPresheaf presheaf composed simplexValue)
      rightAction =
        (applyPresheaf presheaf inner <=< applyPresheaf presheaf outer) simplexValue
   in leftAction == rightAction