packages feed

symtegration-0.6.1: src/Symtegration/Integration/Term.hs

-- |
-- Module: Symtegration.Integration.Term
-- Description: Integrates a single term.
-- Copyright: Copyright 2025 Yoo Chung
-- License: Apache-2.0
-- Maintainer: dev@chungyc.org
module Symtegration.Integration.Term (integrate) where

import Data.Foldable (asum)
import Data.Text (Text)
import Symtegration.Integration.Factor
import Symtegration.Symbolic
import Symtegration.Symbolic.Simplify

-- $setup
-- >>> import Symtegration.Symbolic.Haskell
-- >>> import Symtegration.Symbolic.Simplify

-- | Integrate a single term, separating out the constant factor and
-- applying direct integration methods to the non-constant factor.
--
-- >>> import Symtegration.Integration.Trigonometric qualified as T
-- >>> let f = "a" * sin "x"
-- >>> T.integrate "x" f
-- Nothing
-- >>> let g = integrate [T.integrate] "x" f
-- >>> toHaskell . simplify <$> g
-- Just "(-1) * a * cos x"
--
-- Assumes the expression has had algebraic ring ordering applied.
integrate ::
  -- | Functions for directly integrating the non-constant factor.
  [Text -> Expression -> Maybe Expression] ->
  -- | The variable being integrated over.
  Text ->
  -- | The expression being integrated.
  Expression ->
  -- | The integral, if successful.
  Maybe Expression
integrate fs v e = asum $ map (\f -> (:*:) c <$> f v u) fs
  where
    e' = simplifyForVariable v e
    (c, u) = factor v e'