diff --git a/dataframe-learn.cabal b/dataframe-learn.cabal
--- a/dataframe-learn.cabal
+++ b/dataframe-learn.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.4
 name:               dataframe-learn
-version:            2.4.1.0
+version:            2.4.2.0
 synopsis:           Interpretable, expression-returning machine learning for the dataframe ecosystem.
 description:
     A small scikit-learn-style ML library where every model returns both an
@@ -61,8 +61,8 @@
                         containers >= 0.6.7 && < 0.10,
                         parallel >= 3.3 && < 4,
                         random >= 1.2 && < 2,
-                        dataframe-core >= 2.4 && < 2.5,
-                        dataframe-operations >= 2.4 && < 2.5,
+                        dataframe-core >= 2.5 && < 2.6,
+                        dataframe-operations >= 2.5 && < 2.6,
                         text >= 2.1 && < 3,
                         vector >= 0.13 && < 0.15,
                         vector-algorithms >= 0.9 && < 0.11
@@ -105,11 +105,11 @@
                         containers >= 0.6.7 && < 0.10,
                         parallel >= 3.3 && < 4,
                         random >= 1.2 && < 2,
-                        dataframe-core >= 2.4 && < 2.5,
-                        dataframe-core >= 2.4 && < 2.5,
-                        dataframe-operations >= 2.4 && < 2.5,
-                        dataframe-operations >= 2.4 && < 2.5,
-                        dataframe-expr-serializer >= 1.2.0.1 && < 1.3,
+                        dataframe-core >= 2.5 && < 2.6,
+                        dataframe-core >= 2.5 && < 2.6,
+                        dataframe-operations >= 2.5 && < 2.6,
+                        dataframe-operations >= 2.5 && < 2.6,
+                        dataframe-expr-serializer >= 1.2.1 && < 1.3,
                         dataframe-learn:internal,
                         text >= 2.1 && < 3,
                         vector >= 0.13 && < 0.15
@@ -140,13 +140,13 @@
                         aeson >= 0.11.0.0 && < 3,
                         bytestring >= 0.11 && < 0.14,
                         containers >= 0.6.7 && < 0.10,
-                        dataframe-core >= 2.4 && < 2.5,
-                        dataframe-core >= 2.4 && < 2.5,
+                        dataframe-core >= 2.5 && < 2.6,
+                        dataframe-core >= 2.5 && < 2.6,
                         dataframe-csv >= 2.3 && < 2.4,
                         dataframe-learn,
                         dataframe-learn:internal,
-                        dataframe-operations >= 2.4 && < 2.5,
-                        dataframe-operations >= 2.4 && < 2.5,
+                        dataframe-operations >= 2.5 && < 2.6,
+                        dataframe-operations >= 2.5 && < 2.6,
                         HUnit >= 1.6 && < 1.8,
                         QuickCheck >= 2 && < 3,
                         random >= 1 && < 2,
diff --git a/src-internal/DataFrame/DecisionTree/Cart.hs b/src-internal/DataFrame/DecisionTree/Cart.hs
--- a/src-internal/DataFrame/DecisionTree/Cart.hs
+++ b/src-internal/DataFrame/DecisionTree/Cart.hs
@@ -19,6 +19,7 @@
 
 import DataFrame.DecisionTree.Types (Tree (..), TreeConfig (..))
 import DataFrame.Errors (DataFrameException (..), TypeErrorContext (..))
+import DataFrame.Expression.Operators
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.Column
 import DataFrame.Internal.DataFrame (
@@ -29,9 +30,7 @@
  )
 import DataFrame.Internal.Expression (Expr (..))
 import DataFrame.Internal.Interpreter (interpret)
-import DataFrame.Internal.Types
 import DataFrame.Operations.Core (nRows)
-import DataFrame.Operators
 
 import Control.Exception (throw)
 import Data.Either (fromRight)
diff --git a/src-internal/DataFrame/DecisionTree/Categorical.hs b/src-internal/DataFrame/DecisionTree/Categorical.hs
--- a/src-internal/DataFrame/DecisionTree/Categorical.hs
+++ b/src-internal/DataFrame/DecisionTree/Categorical.hs
@@ -35,12 +35,12 @@
     TreeConfig (..),
     withOrdFrom,
  )
+import DataFrame.Expression.Operators
 import DataFrame.Internal.Column
+import DataFrame.Internal.Column.Bitmap
 import DataFrame.Internal.DataFrame (DataFrame, columnNames, unsafeGetColumn)
 import DataFrame.Internal.Expression (Expr (..))
 import DataFrame.Internal.Interpreter (interpret)
-import DataFrame.Internal.Types
-import DataFrame.Operators
 
 import Data.Either (fromRight)
 import Data.Function (on)
diff --git a/src-internal/DataFrame/DecisionTree/Numeric.hs b/src-internal/DataFrame/DecisionTree/Numeric.hs
--- a/src-internal/DataFrame/DecisionTree/Numeric.hs
+++ b/src-internal/DataFrame/DecisionTree/Numeric.hs
@@ -27,13 +27,12 @@
 
 import DataFrame.DecisionTree.CondVec (CondVec (..), materializeCondVec)
 import DataFrame.DecisionTree.Types (SynthConfig (..), TreeConfig (..))
+import DataFrame.Expression.Operators
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.Column
 import DataFrame.Internal.DataFrame (DataFrame, columnNames, unsafeGetColumn)
 import DataFrame.Internal.Expression (Expr (..), eqExpr, getColumns, normalize)
 import DataFrame.Internal.Interpreter (interpret)
-import DataFrame.Internal.Types
-import DataFrame.Operators
 
 import Data.List (sort)
 import Data.Maybe (catMaybes, mapMaybe)
diff --git a/src-internal/DataFrame/DecisionTree/Prune.hs b/src-internal/DataFrame/DecisionTree/Prune.hs
--- a/src-internal/DataFrame/DecisionTree/Prune.hs
+++ b/src-internal/DataFrame/DecisionTree/Prune.hs
@@ -15,7 +15,12 @@
 import DataFrame.DecisionTree.Types (Tree (..))
 import DataFrame.Internal.Column (Columnable)
 import DataFrame.Internal.Expression (Expr (..), eqExpr)
-import DataFrame.Internal.Simplify (PredFact, entails, factFalse, factTrue)
+import DataFrame.Internal.Expression.Simplify (
+    PredFact,
+    entails,
+    factFalse,
+    factTrue,
+ )
 
 {- | Drop branches whose test is forced by the path conditions reaching them,
 and collapse @Branch c t t@ to @t@. Sound for the decidable threshold subset;
diff --git a/src-internal/DataFrame/Featurize/Internal.hs b/src-internal/DataFrame/Featurize/Internal.hs
--- a/src-internal/DataFrame/Featurize/Internal.hs
+++ b/src-internal/DataFrame/Featurize/Internal.hs
@@ -35,6 +35,13 @@
 
 import Data.Either (fromRight)
 import DataFrame.Errors (DataFrameException (..), TypeErrorContext (..))
+import DataFrame.Expression.Operators (
+    (.&&.),
+    (.*.),
+    (.+.),
+    (.<=.),
+    (.>=.),
+ )
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.Column (Columnable, columnBitmap, columnTypeString)
 import qualified DataFrame.Internal.Column as D
@@ -46,7 +53,6 @@
     columnAsUnboxedVector,
     columnAsVector,
  )
-import DataFrame.Operators ((.&&.), (.*.), (.+.), (.<=.), (.>=.))
 
 -- | Every column name except the supervised target's.
 featureNames :: Expr a -> DataFrame -> [T.Text]
diff --git a/src-internal/DataFrame/LinearSolver.hs b/src-internal/DataFrame/LinearSolver.hs
--- a/src-internal/DataFrame/LinearSolver.hs
+++ b/src-internal/DataFrame/LinearSolver.hs
@@ -28,6 +28,7 @@
     dotProduct,
 ) where
 
+import DataFrame.Expression.Operators ((.*.), (.+.), (.>.))
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.Expression (Expr (..))
 import DataFrame.LinearAlgebra (Matrix, gram, scaleV)
@@ -37,7 +38,6 @@
     logisticLoss,
     sigmoid,
  )
-import DataFrame.Operators ((.*.), (.+.), (.>.))
 
 import Control.Monad.ST (ST, runST)
 import qualified Data.Text as T
diff --git a/src-internal/DataFrame/SymbolicRegression/Expr.hs b/src-internal/DataFrame/SymbolicRegression/Expr.hs
--- a/src-internal/DataFrame/SymbolicRegression/Expr.hs
+++ b/src-internal/DataFrame/SymbolicRegression/Expr.hs
@@ -21,9 +21,9 @@
 import qualified Data.Vector as V
 import qualified Data.Vector.Unboxed as VU
 
+import DataFrame.Expression.Operators ((.*.), (.+.), (.-.), (./.))
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.Expression (Expr (..))
-import DataFrame.Operators ((.*.), (.+.), (.-.), (./.))
 
 data BinOp = SAdd | SSub | SMul | SDiv
     deriving (Eq, Ord, Show, Enum, Bounded)
diff --git a/src/DataFrame/Boosting/AdaBoost.hs b/src/DataFrame/Boosting/AdaBoost.hs
--- a/src/DataFrame/Boosting/AdaBoost.hs
+++ b/src/DataFrame/Boosting/AdaBoost.hs
@@ -35,6 +35,7 @@
  )
 import DataFrame.DecisionTree.Fit (treeToExpr)
 import DataFrame.DecisionTree.Types (Tree (..))
+import DataFrame.Expression.Operators ((.*.), (.+.), (.==.))
 import DataFrame.Featurize.Internal (argMaxExpr, targetValues)
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.Column (Columnable, TypedColumn (..), toVector)
@@ -42,7 +43,6 @@
 import DataFrame.Internal.Expression (Expr (..))
 import DataFrame.Internal.Interpreter (interpret)
 import DataFrame.Model
-import DataFrame.Operators ((.*.), (.+.), (.==.))
 
 data AdaBoostConfig = AdaBoostConfig
     { abNEstimators :: !Int
diff --git a/src/DataFrame/Boosting/GBM.hs b/src/DataFrame/Boosting/GBM.hs
--- a/src/DataFrame/Boosting/GBM.hs
+++ b/src/DataFrame/Boosting/GBM.hs
@@ -35,6 +35,7 @@
 import DataFrame.DecisionTree.Fit (treeToExpr)
 import DataFrame.DecisionTree.Regression (RegTreeConfig (..), fitRegTreeOn)
 import DataFrame.DecisionTree.Types (Tree)
+import DataFrame.Expression.Operators ((.*.), (.+.), (.>.))
 import DataFrame.Featurize.Internal (targetDoubles)
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.Column (TypedColumn (..), toVector)
@@ -42,7 +43,6 @@
 import DataFrame.Internal.Expression (Expr (..), getColumns)
 import DataFrame.Internal.Interpreter (interpret)
 import DataFrame.Model
-import DataFrame.Operators ((.*.), (.+.), (.>.))
 
 -- | The boosting loss.
 data GBLoss = SquaredError | LogisticDeviance
diff --git a/src/DataFrame/GMM.hs b/src/DataFrame/GMM.hs
--- a/src/DataFrame/GMM.hs
+++ b/src/DataFrame/GMM.hs
@@ -29,6 +29,7 @@
 import qualified Data.Vector as V
 import qualified Data.Vector.Unboxed as VU
 
+import DataFrame.Expression.Operators ((.*.), (.+.), (.-.))
 import DataFrame.Featurize.Internal (Features (..), argMaxExpr, extractFeatures)
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.DataFrame (DataFrame)
@@ -36,7 +37,6 @@
 import DataFrame.LinearAlgebra (Matrix, logSumExp)
 import DataFrame.LinearAlgebra.Solve (backSubst, cholesky, forwardSubst)
 import DataFrame.Model
-import DataFrame.Operators ((.*.), (.+.), (.-.))
 import DataFrame.Random (mkGen, sampleIndices)
 
 data CovType = FullCov | DiagCov
diff --git a/src/DataFrame/KMeans.hs b/src/DataFrame/KMeans.hs
--- a/src/DataFrame/KMeans.hs
+++ b/src/DataFrame/KMeans.hs
@@ -25,13 +25,13 @@
 import qualified Data.Vector as V
 import qualified Data.Vector.Unboxed as VU
 
+import DataFrame.Expression.Operators ((.*.), (.+.), (.-.))
 import DataFrame.Featurize.Internal (Features (..), argMinExpr, extractFeatures)
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.DataFrame (DataFrame)
 import DataFrame.Internal.Expression (Expr (..), UExpr (..))
 import DataFrame.LinearAlgebra (Matrix, nearestCenter, sqDist)
 import DataFrame.Model
-import DataFrame.Operators ((.*.), (.+.), (.-.))
 import DataFrame.Random (Gen, mkGen, nextDouble, nextIntR, splitGen)
 import DataFrame.Transform (Transform (..))
 
diff --git a/src/DataFrame/PCA.hs b/src/DataFrame/PCA.hs
--- a/src/DataFrame/PCA.hs
+++ b/src/DataFrame/PCA.hs
@@ -23,6 +23,7 @@
 import qualified Data.Vector as V
 import qualified Data.Vector.Unboxed as VU
 
+import DataFrame.Expression.Operators ((.*.), (.+.), (.-.))
 import DataFrame.Featurize.Internal (Features (..), extractFeatures)
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.DataFrame (DataFrame)
@@ -30,7 +31,6 @@
 import DataFrame.LinearAlgebra (gram)
 import DataFrame.LinearAlgebra.Eigen (jacobiEigenSym)
 import DataFrame.Model
-import DataFrame.Operators ((.*.), (.+.), (.-.))
 import DataFrame.Transform (Transform (..))
 
 -- | How many components to keep.
diff --git a/src/DataFrame/PCA/Kernel.hs b/src/DataFrame/PCA/Kernel.hs
--- a/src/DataFrame/PCA/Kernel.hs
+++ b/src/DataFrame/PCA/Kernel.hs
@@ -21,6 +21,7 @@
 import qualified Data.Vector as V
 import qualified Data.Vector.Unboxed as VU
 
+import DataFrame.Expression.Operators ((.*.), (.+.), (.-.))
 import DataFrame.Featurize.Internal (Features (..), extractFeatures)
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.DataFrame (DataFrame)
@@ -28,7 +29,6 @@
 import DataFrame.LinearAlgebra (sqDist)
 import DataFrame.LinearAlgebra.Eigen (jacobiEigenSym)
 import DataFrame.Model
-import DataFrame.Operators ((.*.), (.+.), (.-.))
 import DataFrame.Random (mkGen, sampleIndices)
 import DataFrame.Transform (Transform (..))
 
diff --git a/src/DataFrame/SVM/RFF.hs b/src/DataFrame/SVM/RFF.hs
--- a/src/DataFrame/SVM/RFF.hs
+++ b/src/DataFrame/SVM/RFF.hs
@@ -25,6 +25,7 @@
 import qualified Data.Vector.Unboxed as VU
 import DataFrame.Errors (DataFrameException (..))
 
+import DataFrame.Expression.Operators ((.*.), (.+.), (.>.))
 import DataFrame.Featurize.Internal (featureNames, numericMatrix, targetValues)
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.Column (Columnable)
@@ -34,7 +35,6 @@
 import DataFrame.LinearSolver (LinearModel (..), SolverConfig (..), fitProx)
 import DataFrame.LinearSolver.Loss (sqHingeLoss)
 import DataFrame.Model
-import DataFrame.Operators ((.*.), (.+.), (.>.))
 import DataFrame.Random (Gen, gaussianVector, mkGen, nextDouble)
 
 data RFFConfig = RFFConfig
diff --git a/src/DataFrame/Segmented.hs b/src/DataFrame/Segmented.hs
--- a/src/DataFrame/Segmented.hs
+++ b/src/DataFrame/Segmented.hs
@@ -34,17 +34,19 @@
 import qualified Data.Vector.Unboxed as VU
 import DataFrame.Errors (DataFrameException (..))
 
+import DataFrame.Expression.Operators ((.&&.), (.==.))
 import DataFrame.Featurize.Internal (featureNames, numericMatrix, targetDoubles)
 import DataFrame.Internal.Column (
     Column (..),
     Columnable,
-    bitmapTestBit,
     columnBitmap,
+    columnToTextVec,
     hasElemType,
  )
+import DataFrame.Internal.Column.Bitmap (bitmapTestBit)
+import DataFrame.Internal.Column.Types (SBool (..), sIntegral)
 import DataFrame.Internal.DataFrame (DataFrame, unsafeGetColumn)
 import DataFrame.Internal.Expression (Expr (..))
-import DataFrame.Internal.Types (SBool (..), sIntegral)
 import DataFrame.LinearAlgebra (Matrix, gram, matVec, tMatVec)
 import DataFrame.LinearAlgebra.Solve (choleskySolve, qrLeastSquares)
 import DataFrame.LinearModel.Logistic (LogisticConfig)
@@ -54,8 +56,7 @@
  )
 import DataFrame.Model
 import DataFrame.Operations.Core (nRows)
-import DataFrame.Operations.Subset (columnToTextVec, exclude, rowsAtIndices)
-import DataFrame.Operators ((.&&.), (.==.))
+import DataFrame.Operations.Subset (exclude, rowsAtIndices)
 import DataFrame.SymbolicRegression (SRConfig)
 
 {- | A base estimator @cfg@ wrapped to fit one model per categorical
diff --git a/src/DataFrame/Transform.hs b/src/DataFrame/Transform.hs
--- a/src/DataFrame/Transform.hs
+++ b/src/DataFrame/Transform.hs
@@ -26,6 +26,7 @@
 import qualified Data.Vector as V
 import qualified Data.Vector.Unboxed as VU
 
+import DataFrame.Expression.Operators ((.-.), (./.))
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.Column (Columnable)
 import DataFrame.Internal.DataFrame (DataFrame)
@@ -37,7 +38,6 @@
  )
 import DataFrame.Operations.Core (columnAsDoubleVector)
 import DataFrame.Operations.Transformations (deriveMany)
-import DataFrame.Operators ((.-.), (./.))
 
 -- | A fitted transform: named output columns derived from the input frame.
 newtype Transform = Transform {transformOutputs :: [NamedExpr]}
diff --git a/tests-internal/DecisionTree.hs b/tests-internal/DecisionTree.hs
--- a/tests-internal/DecisionTree.hs
+++ b/tests-internal/DecisionTree.hs
@@ -43,13 +43,14 @@
  )
 import DataFrame.DecisionTree.Tao (taoIteration, taoOptimize)
 import DataFrame.DecisionTree.Types (CarePoint (..), Direction (..))
+import DataFrame.Expression.Operators
 import qualified DataFrame.Functions as F
 import qualified DataFrame.Internal.Column as DI
+import qualified DataFrame.Internal.Column.Bitmap as DI
+import DataFrame.Internal.Data.PackedText (mkPackedContiguous)
 import DataFrame.Internal.Expression (Expr (..), eqExpr, getColumns)
 import DataFrame.Internal.Interpreter (interpret)
-import DataFrame.Internal.PackedText (mkPackedContiguous)
 import qualified DataFrame.LinearSolver
-import DataFrame.Operators
 import qualified DataFrameApi as D
 
 import Control.Monad (zipWithM_)
diff --git a/tests-internal/Properties/Simplify.hs b/tests-internal/Properties/Simplify.hs
--- a/tests-internal/Properties/Simplify.hs
+++ b/tests-internal/Properties/Simplify.hs
@@ -11,13 +11,13 @@
 import DataFrame.DecisionTree.Predict (predictWithTree)
 import DataFrame.DecisionTree.Prune (pruneDead)
 import DataFrame.DecisionTree.Types (Tree (..))
+import DataFrame.Expression.Operators
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.Column (TypedColumn (TColumn), toVector)
 import qualified DataFrame.Internal.Column as DI
 import DataFrame.Internal.Expression (Expr, eqExpr)
+import DataFrame.Internal.Expression.Simplify (simplify)
 import DataFrame.Internal.Interpreter (interpret)
-import DataFrame.Internal.Simplify (simplify)
-import DataFrame.Operators
 import qualified DataFrameApi as D
 
 import qualified Data.Text as T
diff --git a/tests-internal/TreePruning.hs b/tests-internal/TreePruning.hs
--- a/tests-internal/TreePruning.hs
+++ b/tests-internal/TreePruning.hs
@@ -8,9 +8,9 @@
 
 import DataFrame.DecisionTree.Prune (pruneDead)
 import DataFrame.DecisionTree.Types (Tree (..))
+import DataFrame.Expression.Operators
 import qualified DataFrame.Functions as F
 import DataFrame.Internal.Expression (eqExpr)
-import DataFrame.Operators
 
 import qualified Data.Text as T
 import Test.HUnit
diff --git a/tests-internal/Worklist.hs b/tests-internal/Worklist.hs
--- a/tests-internal/Worklist.hs
+++ b/tests-internal/Worklist.hs
@@ -18,6 +18,7 @@
     boolExprsVec,
     saturateCandidates,
  )
+import DataFrame.Expression.Operators
 import qualified DataFrame.Functions as F
 import qualified DataFrame.Internal.Column as DI
 import DataFrame.Internal.Expression (
@@ -27,7 +28,6 @@
     eqExpr,
     normalize,
  )
-import DataFrame.Operators
 import qualified DataFrameApi as D
 
 import Data.Function (on)
