packages feed

moonlight-core-0.1.0.0: README.md

# moonlight-core

> Part of **Moonlight**, the sheaf-theoretic computation layer beneath
> [Melusine](https://bluerose.blue) and Pale Meridian.

`moonlight-core` is Moonlight's foundation tier.
It is the total vocabulary every layer above shares: numeric classes, structural
identity, orders, patterns, fixpoints, persistent union-find, finite registries, a
term database, and a host-neutral e-graph program algebra.

## Main idea

Every name reachable from the one import, `Moonlight.Core`, is total. Failure is a
value in the return type: `tryInv` returns `Maybe`, `makeSet` returns
`Either UnionFindAllocationError`, `fixpointBounded` returns
`Either (FixpointDivergence a)`, `mkTotalRegistry` returns `Either [missingKey]`.
Operations with no failure case (`magnitude`, `neg`, `union`) return bare values.

`Moonlight.Core.Unsound` holds the unchecked constructors: importing it by name
asserts a refinement the checker cannot see. Every other constructor reachable
through the umbrella validates at construction.

## Use

```haskell
import Moonlight.Core

reciprocalOfThree :: Maybe Double
reciprocalOfThree = tryInv 3

size :: Double
size = magnitude (neg (2.5 :: Double))
```

## Cookbook

Each recipe shows the main idea in practice: the total path returns a value, the
failure path returns a typed sum.

### Persistent union-find

`makeSet` mints fresh classes through a checked allocation boundary, `union`
merges them, and the structure is persistent; older versions stay valid after a
merge.

```haskell
import Moonlight.Core

partition :: Either UnionFindAllocationError (Bool, Bool)
partition = do
  (a, uf1) <- makeSet emptyUnionFind
  (b, uf2) <- makeSet uf1
  (c, uf3) <- makeSet uf2
  let uf = union a b uf3
  pure (equivalent a b uf, equivalent a c uf)   -- Right (True, False)
```

### Bounded fixpoints

`fixpointBounded` iterates a step to a fixed point under an explicit fuel bound.
Non-convergence returns a typed `Left`.

```haskell
import Moonlight.Core

converge :: Either (FixpointDivergence Int) Int
converge = fixpointBounded 100 (\n -> n `div` 2) 37   -- Right 0

diverges :: Either (FixpointDivergence Int) Int
diverges = fixpointBounded 5 (+1) 0                   -- Left (out of fuel)
```

### Checked total maps

`mkTotalRegistry` demands every key of a finite universe; a gap is a typed
`Left [missingKeys]`. In exchange, `lookupTotal` returns a bare value once the
registry is constructed.

```haskell
import Moonlight.Core
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.Map.Strict as Map

data Slot = Alpha | Beta | Gamma
  deriving (Eq, Ord, Show)

instance FiniteUniverse Slot where
  finiteUniverse = Alpha :| [Beta, Gamma]

palette :: Either [Slot] (TotalRegistry Slot String)
palette = mkTotalRegistry (Map.fromList [(Alpha, "a"), (Beta, "b"), (Gamma, "c")])

labelOfBeta :: Either [Slot] String
labelOfBeta = fmap (\reg -> lookupTotal reg Beta) palette   -- Right "b"
-- mkTotalRegistry (Map.fromList [(Alpha, "a")])  ==  Left [Beta, Gamma]
```

### The matching seam

`ZipMatch` is one-layer structural matching: `zipMatch` succeeds iff two nodes share a
shape, pairing their children positionally. It is the seam the e-graph and rewriting
layers are built on.

```haskell
import Moonlight.Core

data ExprF a = Lit Int | Add a a
  deriving (Functor, Foldable, Traversable, Eq, Ord, Show)

instance ZipMatch ExprF where
  zipMatch (Lit m)     (Lit n)     | m == n = Just (Lit m)
  zipMatch (Add a1 b1) (Add a2 b2)          = Just (Add (a1, a2) (b1, b2))
  zipMatch _           _                    = Nothing

aligned :: Maybe (ExprF (Int, Int))
aligned = zipMatch (Add 1 2) (Add 10 20)   -- Just (Add (1,10) (2,20))
```

## Surface & boundaries

Most downstream code imports the umbrella. Lower-level packages may depend on one
of the public sublibraries.

| Cabal dependency | Import | What you get |
| --- | --- | --- |
| `moonlight-core` | `Moonlight.Core` | The ordinary total vocabulary. This is the default. |
| `moonlight-core:moonlight-core-syntax` | `Moonlight.Core.Pattern.AntiUnify` | Patterns and term anti-unification without the full umbrella. |
| `moonlight-core:moonlight-core-automata` | `Moonlight.Core.Pattern.Automata` or `.Kernel` | The bottom-up automata substrate and compiled matcher. Depend on syntax too when naming its types directly. |
| `moonlight-core:moonlight-core-egraph-program` | `Moonlight.Core.EGraph.Program` | The host-neutral e-graph program algebra without the rest of the foundation. |
| `moonlight-core` | `Moonlight.Core.Unsound` | The explicit trust boundary; see [Main idea](#main-idea). |

The private implementation slices remain **basis**, **numeric**, **solver**, and
**term**. Syntax, automata, and e-graph programs are public because other foundation
packages consume those exact owners. The umbrella re-exports the
syntax and e-graph-program vocabulary; automata are imported only through the sublibrary.
Haddock carries the signatures; the laws are named and machine-checked in the law suites.

## Test

```bash
cabal test moonlight-core:moonlight-core-test
```

## Benchmarks

```bash
cabal bench moonlight-core:moonlight-core-bench --benchmark-options='--timeout=2s --csv=comparison.csv'
```

`hackage:` rows measure a package-level baseline (`containers`, `memory`, `scientific`,
`equivalence`) on the same fixture; `world:` rows are source-equivalent baselines where
no package owner exists. Fixtures assert result agreement with the baseline before
timing. Dated receipts live in `docs/BENCHMARKS-m4-pro.md`.

## License

MIT. See `LICENSE`.