moonlight-core 0.1.0.2 → 0.1.0.3
raw patch · 11 files changed
+94/−41 lines, 11 filesdep ~basedep ~deepseq
Dependency ranges changed: base, deepseq
Files
- CHANGELOG.md +13/−0
- LICENSE +1/−1
- moonlight-core.cabal +23/−12
- src-basis/Moonlight/Core/Error.hs +9/−3
- src-basis/Moonlight/Core/MapAccum.hs +8/−2
- src-basis/Moonlight/Core/Validation.hs +7/−0
- src-solver/Moonlight/Core/UnionFind.hs +8/−0
- src-solver/Moonlight/Core/UnionFind/Transaction.hs +10/−0
- test/aggregate/Main.hs +0/−22
- test/basis/TotalRegistrySpec.hs +1/−1
- test/coherence/Main.hs +14/−0
CHANGELOG.md view
@@ -1,5 +1,18 @@ # Changelog +## 0.1.0.3 - 2026-08-20++- Compatibility: the `Moonlight.Core` main-library closure now supports GHC+ 9.10.3, 9.12.4, and 9.14.1 (`base >= 4.20`). The independent `automata`+ component retains its existing GHC 9.14 floor.++- Performance: `Moonlight.Core.MapAccum.accumByKey` now folds rightwards, so a+ list-shaped value costs time linear in each key's group rather than+ quadratic. The documented input-order law is unchanged. Its hot consumer is+ saturation's raw-match grouping by rule key, where one rule matching `k`+ roots previously paid `k^2`; measured downstream gain is 2.14x to 2.62x on+ the `moonlight-saturation` engine benchmark lane at its largest scale.+ ## 0.1.0.2 - 2026-07-22 - Documentation: the `Moonlight.Core` umbrella header now carries the worked
LICENSE view
@@ -1,6 +1,6 @@ MIT License -Copyright (c) 2026 The Blue Rose, Rosalia Fialkova+Copyright (c) 2026 Blue Rose Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
moonlight-core.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: moonlight-core-version: 0.1.0.2+version: 0.1.0.3 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@@ -12,7 +12,7 @@ homepage: https://github.com/PaleRoses/moonlight bug-reports: https://github.com/PaleRoses/moonlight/issues build-type: Simple-tested-with: GHC == 9.14.1+tested-with: GHC == 9.10.3, GHC == 9.12.4, GHC == 9.14.1 extra-doc-files: README.md CHANGELOG.md@@ -22,6 +22,12 @@ location: https://github.com/PaleRoses/moonlight.git subdir: moonlight-core +source-repository this+ type: git+ location: https://github.com/PaleRoses/moonlight.git+ tag: moonlight-core-0.1.0.3+ subdir: moonlight-core+ common shared-properties default-language: GHC2024 ghc-options:@@ -75,9 +81,10 @@ Moonlight.Core.Validation Moonlight.Internal.Unsound build-depends:- base >= 4.22 && < 5+ base >= 4.20 && < 5 , bytestring >= 0.11 && < 0.13 , containers >= 0.8 && < 0.9+ , deepseq >= 1.5 && < 1.6 , memory >= 0.18 && < 0.19 , text >= 2.0 && < 2.2 @@ -88,7 +95,7 @@ exposed-modules: Moonlight.Core.EGraph.Program build-depends:- base >= 4.22 && < 5+ base >= 4.20 && < 5 , free >= 5.2 && < 6 , moonlight-core:moonlight-core-basis @@ -110,7 +117,7 @@ Moonlight.Core.Niche.Internal Moonlight.Internal.FloatMath build-depends:- base >= 4.22 && < 5+ base >= 4.20 && < 5 , bytestring >= 0.11 && < 0.13 , containers >= 0.8 && < 0.9 , moonlight-core:moonlight-core-basis@@ -130,7 +137,7 @@ Moonlight.Core.Substitution Moonlight.Core.Theory build-depends:- base >= 4.22 && < 5+ base >= 4.20 && < 5 , containers >= 0.8 && < 0.9 , data-fix >= 0.3 && < 0.4 , moonlight-core:moonlight-core-basis@@ -140,6 +147,8 @@ import: shared-properties visibility: public hs-source-dirs: src-automata+ if impl(ghc < 9.14)+ buildable: False default-extensions: NoStrictData exposed-modules:@@ -196,7 +205,7 @@ Moonlight.Core.UnionFind.Internal.Semantics Moonlight.Core.UnionFind.Internal.Types build-depends:- base >= 4.22 && < 5+ base >= 4.20 && < 5 , containers >= 0.8 && < 0.9 , deepseq >= 1.4 && < 1.6 , free >= 5.2 && < 6@@ -226,7 +235,7 @@ Moonlight.Core.Term.Database.Transaction Moonlight.Core.Term.Database.Types build-depends:- base >= 4.22 && < 5+ base >= 4.20 && < 5 , containers >= 0.8 && < 0.9 , moonlight-core:moonlight-core-basis , moonlight-core:syntax@@ -241,7 +250,7 @@ reexported-modules: Moonlight.Core.Unsound build-depends:- base >= 4.22 && < 5+ base >= 4.20 && < 5 , containers >= 0.8 && < 0.9 , moonlight-core:egraph-program , moonlight-core:moonlight-core-numeric@@ -252,7 +261,7 @@ common moonlight-core-test-properties default-language: GHC2024- ghc-options: -Wall -Wcompat+ ghc-options: -Wall -Wcompat -O0 default-extensions: TypeFamilies build-depends:@@ -358,11 +367,13 @@ PublicSurfaceSpec SourceShape -test-suite moonlight-core-test+-- The focused suites own behavior. This component owns only the union of their+-- module, instance, and dependency surfaces, compiled at the shared test O0.+test-suite moonlight-core-coherence-test import: moonlight-core-test-properties type: exitcode-stdio-1.0 hs-source-dirs:- test/aggregate+ test/coherence test/basis test/numeric test/syntax
src-basis/Moonlight/Core/Error.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveAnyClass #-} -- | Shared error vocabulary for checked numeric construction; each constructor names the violated precondition. module Moonlight.Core.Error@@ -8,8 +9,10 @@ ) where +import Control.DeepSeq (NFData) import Data.Kind (Type) import Data.Word (Word32)+import GHC.Generics (Generic) import Prelude (Eq, Show, String, show, (<>)) type MoonlightErrorContext :: Type@@ -17,13 +20,15 @@ = CanonicalizeContext | QuantizeContext | DomainContext !String- deriving stock (Eq, Show)+ deriving stock (Eq, Show, Generic)+ deriving anyclass (NFData) type NonFiniteInput :: Type data NonFiniteInput = NaNInput | InfiniteInput- deriving stock (Eq, Show)+ deriving stock (Eq, Show, Generic)+ deriving anyclass (NFData) type MoonlightError :: Type data MoonlightError@@ -33,7 +38,8 @@ | NegativeValue !MoonlightErrorContext | NonCanonicalFiniteValue | InvariantViolation !String- deriving stock (Eq, Show)+ deriving stock (Eq, Show, Generic)+ deriving anyclass (NFData) renderMoonlightError :: MoonlightError -> String renderMoonlightError errorValue =
src-basis/Moonlight/Core/MapAccum.hs view
@@ -33,10 +33,16 @@ groupByKey :: Ord k => (a -> k) -> [a] -> Map k [a] groupByKey keyOf = foldr (insertGroupedValue keyOf) Map.empty +-- | Accumulate values by key, combining them in input order.+--+-- Folding rightwards keeps every combination right-associated, so a+-- list-shaped value costs time linear in the group rather than quadratic.+-- Accumulating leftwards would append each new value to the end of an+-- ever-longer left operand. accumByKey :: (Ord k, Semigroup v) => (a -> k) -> (a -> v) -> [a] -> Map k v accumByKey keyOf valueOf =- foldl'- (\acc value -> Map.insertWith (\newValue oldValue -> oldValue <> newValue) (keyOf value) (valueOf value) acc)+ foldr+ (\value acc -> Map.insertWith (<>) (keyOf value) (valueOf value) acc) Map.empty buildTripleIndex ::
src-basis/Moonlight/Core/Validation.hs view
@@ -5,10 +5,12 @@ validationToEither, mapValidationError, collectEither,+ validationFromErrors, ) where import Data.Kind (Type)+import Data.List.NonEmpty (NonEmpty, nonEmpty) import Prelude ( Applicative (..), Either (..),@@ -17,6 +19,7 @@ Semigroup ((<>)), Show, Traversable (traverse),+ maybe, ) type Validation :: Type -> Type -> Type@@ -65,3 +68,7 @@ collectEither eitherValues = validationToEither (traverse eitherToValidation eitherValues)++validationFromErrors :: [error] -> Validation (NonEmpty error) ()+validationFromErrors errors =+ maybe (Valid ()) Invalid (nonEmpty errors)
src-solver/Moonlight/Core/UnionFind.hs view
@@ -17,6 +17,7 @@ samePartition, canonicalMap, canonicalMapAndCompress,+ compress, ) where @@ -51,6 +52,7 @@ min, otherwise, pure,+ snd, (.), ) @@ -155,6 +157,12 @@ canonicalMapAndCompress :: UnionFind -> (IntMap ClassId, UnionFind) canonicalMapAndCompress unionFind = Transaction.runUnionFindTransaction unionFind Transaction.transactionCanonicalMapAndCompress++-- | Flatten every parent chain to its root, returning the compressed+-- structure.+compress :: UnionFind -> UnionFind+compress unionFind =+ snd (Transaction.runUnionFindTransaction unionFind Transaction.transactionCompress) parentKeyOf :: UnionFind -> Int -> Maybe Int parentKeyOf unionFind key =
src-solver/Moonlight/Core/UnionFind/Transaction.hs view
@@ -22,10 +22,12 @@ transactionUnion, transactionEquivalent, transactionCanonicalMapAndCompress,+ transactionCompress, ) where import Control.Monad.ST (ST, runST)+import Data.Foldable (traverse_) import Data.IntMap.Strict (IntMap) import Data.IntMap.Strict qualified as IntMap import Data.Maybe (isJust)@@ -177,3 +179,11 @@ IntMap.traverseWithKey (\key _ -> transactionFind editor (ClassId key)) currentParents++-- | Compress every parent chain in place; the freeze commits the flat+-- structure.+transactionCompress :: UnionFindEditor state -> ST state ()+transactionCompress editor = do+ currentParents <- parentMap editor+ traverse_ (compressRootKey editor) (IntMap.keys currentParents)+{-# INLINE transactionCompress #-}
− test/aggregate/Main.hs
@@ -1,22 +0,0 @@-module Main where--import qualified BasisTests-import qualified NumericTests-import qualified PublicSurfaceSpec-import qualified SolverTests-import qualified SyntaxTests-import Test.Tasty (defaultMain, testGroup)-import qualified TermTests--main :: IO ()-main =- defaultMain $- testGroup- "moonlight-core"- [ BasisTests.tests,- NumericTests.tests,- SyntaxTests.tests,- SolverTests.tests,- TermTests.tests,- PublicSurfaceSpec.tests- ]
test/basis/TotalRegistrySpec.hs view
@@ -76,7 +76,7 @@ testLookupTotalOutsideUniverseFallback :: IO () testLookupTotalOutsideUniverseFallback =- case mkTotalRegistry (Map.singleton InsideUniverse 99) of+ case mkTotalRegistry (Map.singleton InsideUniverse (99 :: Int)) of Left missingKeys -> assertFailure ("expected registry with the declared finite universe, missing keys: " <> show missingKeys) Right registry ->
+ test/coherence/Main.hs view
@@ -0,0 +1,14 @@+-- | Compile every focused test section against their dependency union. Empty+-- imports retain module and instance coherence without executing the focused+-- behavioral suites a second time.+module Main where++import BasisTests ()+import NumericTests ()+import PublicSurfaceSpec ()+import SolverTests ()+import SyntaxTests ()+import TermTests ()++main :: IO ()+main = pure ()