packages feed

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 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 ()