packages feed

moonlight-homology-0.1.0.0: src-chain/Moonlight/Homology/Pure/Reductions/Core.hs

module Moonlight.Homology.Pure.Reductions.Core
  ( ChainMap (..),
    ChainHomotopy (..),
    Reduction (..),
    ReductionWitness (..),
    ReductionViolation (..),
    ReductionLawContext (..),
    ReductionValidation,
    ReductionChecks (..),
    mkReductionWitness,
  )
where

import Data.Kind (Type)
import Data.List.NonEmpty (NonEmpty ((:|)))
import Moonlight.Core (Validation (..))
import Moonlight.Homology.Pure.Failure (HomologyFailure)

type ChainMap :: Type -> Type -> Type -> Type
newtype ChainMap source target r = ChainMap
  { runChainMap :: source -> [(r, target)]
  }

type ChainHomotopy :: Type -> Type -> Type
newtype ChainHomotopy basis r = ChainHomotopy
  { runChainHomotopy :: basis -> [(r, basis)]
  }

type Reduction :: Type -> Type -> Type -> Type -> Type -> Type
data Reduction large small r largeBasis smallBasis = Reduction
  { projection :: ChainMap largeBasis smallBasis r,
    inclusion :: ChainMap smallBasis largeBasis r,
    homotopy :: ChainHomotopy largeBasis r
  }

type ReductionViolation :: Type
data ReductionViolation
  = ProjectionInclusionIdentityViolation HomologyFailure
  | InclusionProjectionHomotopyViolation HomologyFailure
  | ProjectionChainMapViolation HomologyFailure
  | InclusionChainMapViolation HomologyFailure
  deriving stock (Eq, Show)

type ReductionLawContext :: Type -> Type -> Type -> Type
data ReductionLawContext largeBasis smallBasis r = ReductionLawContext
  { sampledLargeBasis :: [largeBasis],
    sampledSmallBasis :: [smallBasis],
    largeBoundary :: largeBasis -> [(r, largeBasis)],
    smallBoundary :: smallBasis -> [(r, smallBasis)]
  }

type ReductionValidation :: Type -> Type
type ReductionValidation a = Validation (NonEmpty ReductionViolation) a

type ReductionChecks :: Type -> Type -> Type -> Type
data ReductionChecks largeBasis smallBasis r = ReductionChecks
  { checkProjectionInclusionIdentity ::
      ChainMap largeBasis smallBasis r ->
      ChainMap smallBasis largeBasis r ->
      Either ReductionViolation (),
    checkInclusionProjectionHomotopy ::
      ChainMap largeBasis smallBasis r ->
      ChainMap smallBasis largeBasis r ->
      ChainHomotopy largeBasis r ->
      Either ReductionViolation (),
    checkProjectionChainMap ::
      ChainMap largeBasis smallBasis r ->
      Either ReductionViolation (),
    checkInclusionChainMap ::
      ChainMap smallBasis largeBasis r ->
      Either ReductionViolation ()
  }

type ReductionWitness :: Type -> Type -> Type -> Type -> Type -> Type
newtype ReductionWitness large small r largeBasis smallBasis = ReductionWitness
  { checkedReduction :: Reduction large small r largeBasis smallBasis
  }

mkReductionWitness ::
  Reduction large small r largeBasis smallBasis ->
  ReductionChecks largeBasis smallBasis r ->
  ReductionValidation (ReductionWitness large small r largeBasis smallBasis)
mkReductionWitness reduction checks =
  (\_ _ _ _ -> ReductionWitness reduction)
    <$> validate (checkProjectionInclusionIdentity checks projectionMap inclusionMap)
    <*> validate (checkInclusionProjectionHomotopy checks projectionMap inclusionMap homotopyMap)
    <*> validate (checkProjectionChainMap checks projectionMap)
    <*> validate (checkInclusionChainMap checks inclusionMap)
  where
    projectionMap = projection reduction
    inclusionMap = inclusion reduction
    homotopyMap = homotopy reduction
    validate :: Either ReductionViolation () -> ReductionValidation ()
    validate checkResult =
      case checkResult of
        Left violation -> Invalid (violation :| [])
        Right () -> Valid ()