packages feed

moonlight-core 0.1.0.1 → 0.1.0.2

raw patch · 4 files changed

+107/−120 lines, 4 files

Files

CHANGELOG.md view
@@ -1,5 +1,11 @@ # Changelog +## 0.1.0.2 - 2026-07-22++- Documentation: the `Moonlight.Core` umbrella header now carries the worked+  recipes — persistent union-find, bounded fixpoints, checked total maps, and+  the matching seam. The README is reduced to a dependency and module map.+ ## 0.1.0.1 - 2026-07-22  - Public named sublibraries drop the redundant package prefix:
README.md view
@@ -3,118 +3,9 @@ > 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))-```+`moonlight-core` is Moonlight's foundation tier. The front door is the total+umbrella module `Moonlight.Core`; its header carries the contract, the API map,+and the worked recipes. This page is the dependency map and the build commands.  ## Surface & boundaries @@ -127,13 +18,12 @@ | `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). |+| `moonlight-core` | `Moonlight.Core.Unsound` | The explicit trust boundary. |  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 
moonlight-core.cabal view
@@ -1,6 +1,6 @@ cabal-version:       3.0 name:                moonlight-core-version:             0.1.0.1+version:             0.1.0.2 synopsis:            Mathematical basis for Pale Meridian. description:         A total vocabulary of numeric classes, structural identity, orders, patterns, fixpoints, union-find, finite registries, and host-neutral e-graph programs. license:             MIT
src-public/Moonlight/Core.hs view
@@ -1,9 +1,100 @@ {-|-Authoritative frozen umbrella re-export of the moonlight-core foundation-surface. Direct @Moonlight.Core.*@ module imports outside this module are-internal-use-at-own-risk, except for the deliberately explicit-"Moonlight.Core.Unsound" trust boundary. Unsafe refinement constructors are not-re-exported here.+The single, total import of the @moonlight-core@ foundation — the vocabulary+every layer above shares. Every name reachable from @Moonlight.Core@ is+/total/: failure is a value in the return type, never an exception. @tryInv@+returns @Maybe@, @makeSet@ returns @Either UnionFindAllocationError@, and+@fixpointBounded@ returns @Either (FixpointDivergence a)@; operations with no+failure case (@magnitude@, @neg@, @union@) return bare values.++Direct @Moonlight.Core.*@ imports elsewhere are internal-use-at-own-risk, and+the unsafe refinement constructors are not re-exported here. The one deliberate+hole in construction-time checking is "Moonlight.Core.Unsound", whose+constructors assert a refinement the checker cannot see.++The re-exported vocabulary, by role:++* Numeric tower — @Scalar@, @Numeric@ (@OrderedRing@, @OrderedField@,+  @ContinuousField@) and @ApproxEq@, with canonical and exact numbers via+  @Canon@, @CanonicalNumber@, @ExactToken@.+* Validation and refinement — @Validation@, @Refinement@, @Niche@: the+  construction-time checks that back the totality contract.+* Identity and language — @DomainId@, @Identifier@ (with the e-graph+  identifiers and @PatternVar@), @Capability@, @ModuleIdentifier@, and the+  @Language@ / @ZipMatch@ node algebra.+* Theories, patterns and matching — @Theory@, @Pattern@, @Substitution@,+  @Match@: the one-layer structural-matching seam the e-graph and rewriting+  layers stand on.+* Identity hashing — @StableHash@, @Hash@, @DenseKey@.+* Order, finiteness and fixpoints — @Finite@, @Order@, @OrdCollection@,+  @Fix.Order@, and @Fixpoint@ (with the dense solver), which report+  non-convergence as a value.+* Collections and registries — @Aggregate@, @MapAccum@, @MapInvert@, @Queue@,+  @Dedup@, @Scan@, @Relational@, checked-total @TotalRegistry@, and the+  persistent and transactional @UnionFind@.+* Programs and terms — the host-neutral @EGraph.Program@ and @Site.Program@+  algebras and the relational @Term.Database@ with its canonicalization.+* Manifests and metadata — @ProofManifest@, @LawName@, @Guidance@, @Boundary@,+  @Cardinality@, @IsoNorm@, @TypeLevel@, @Error@.++Each module's Haddock carries the signatures; the laws are named through+@LawName@ and machine-checked in the package law suites, not restated here.++Worked recipes follow: the total path returns a value, the failure path a typed+sum. Each assumes @import Moonlight.Core@.++/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.++> 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@ rather than looping.++> 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 (assumes @Data.List.NonEmpty (NonEmpty (..))@+and a qualified @Data.Map.Strict@).++> 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.++> 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)) -} module Moonlight.Core   ( -- * Numeric tower