diff --git a/mealy.cabal b/mealy.cabal
--- a/mealy.cabal
+++ b/mealy.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.0
 name: mealy
-version: 0.5.0.0
+version: 0.5.0.1
 license: BSD-3-Clause
 license-file: LICENSE
 copyright: Tony Day (c) 2013
@@ -11,73 +11,126 @@
 bug-reports: https://github.com/tonyday567/mealy/issues
 synopsis: Mealy machines for processing time-series and ordered data.
 description:
-
-    @mealy@ reimagines statistics as a [mealy machine](https://en.wikipedia.org/wiki/Mealy_machine) processing data with some form of order such as time-series data. The 'Mealy', with the help of a decay function specifying the relative weights of recent values versus older value, can be treated as a compression or summary of the data stream into 'current state.'
-    Mealies are highly polymorphic, situated at a busy crossroad of theory and practice, and lend themselves to ergonmic, compact and realistic representations of a wide range of online phenomena.
+  @mealy@ reimagines statistics as a [mealy machine](https://en.wikipedia.org/wiki/Mealy_machine) processing data with some form of order such as time-series data. The 'Mealy', with the help of a decay function specifying the relative weights of recent values versus older value, can be treated as a compression or summary of the data stream into 'current state.'
+  Mealies are highly polymorphic, situated at a busy crossroad of theory and practice, and lend themselves to ergonmic, compact and realistic representations of a wide range of online phenomena.
 
-    == Usage
+  == Usage
 
-    >>> import Mealy
+  >>> import Mealy
 
-    >>> fold ((,) <$> ma 0.9 <*> std 0.9) [1..100]
-    (91.00265621044142,9.472822805289121)
+  >>> fold ((,) <$> ma 0.9 <*> std 0.9) [1..100]
+  (91.00265621044142,9.472822805289121)
 
 build-type: Simple
 tested-with:
-    , GHC == 9.10.1
-    , GHC == 9.6.5
-    , GHC == 9.8.2
+  ghc ==9.6.7
+  ghc ==9.8.4
+  ghc ==9.10.2
+  ghc ==9.12.2
+
 extra-doc-files:
-    ChangeLog.md
-    readme.org
+  ChangeLog.md
+  readme.org
 
 source-repository head
-    type: git
-    location: https://github.com/tonyday567/mealy
+  type: git
+  location: https://github.com/tonyday567/mealy
 
 common ghc-options-stanza
-    ghc-options:
-        -Wall
-        -Wcompat
-        -Widentities
-        -Wincomplete-record-updates
-        -Wincomplete-uni-patterns
-        -Wpartial-fields
-        -Wredundant-constraints
+  ghc-options:
+    -Wall
+    -Wcompat
+    -Widentities
+    -Wincomplete-record-updates
+    -Wincomplete-uni-patterns
+    -Wpartial-fields
+    -Wredundant-constraints
 
-common ghc2021-stanza
-    default-language: GHC2021
+common ghc2024-additions
+  default-extensions:
+    DataKinds
+    DerivingStrategies
+    DisambiguateRecordFields
+    ExplicitNamespaces
+    GADTs
+    LambdaCase
+    MonoLocalBinds
+    RoleAnnotations
 
+common ghc2024-stanza
+  if impl(ghc >=9.10)
+    default-language:
+      GHC2024
+  else
+    import: ghc2024-additions
+    default-language:
+      GHC2021
+
 library
-    import: ghc-options-stanza
-    import: ghc2021-stanza
-    hs-source-dirs: src
-    build-depends:
-        , adjunctions       >=4.0 && <4.5
-        , base              >=4.14 && <5
-        , containers        >=0.6 && <0.8
-        , mwc-probability   >=2.3.1 && <2.4
-        , numhask           >=0.11 && <0.13
-        , harpie            >=0.1 && <0.2
-        , harpie-numhask    >=0.1 && <0.2
-        , primitive         >=0.7.2 && <0.10
-        , profunctors       >=5.6.2 && <5.7
-        , tdigest           >=0.2.1 && <0.4
-        , text              >=1.2 && <2.2
-        , vector            >=0.12.3 && <0.14
-        , vector-algorithms >=0.8.0 && <0.10
-    exposed-modules:
-        Data.Mealy
-        Data.Mealy.Quantiles
-        Data.Mealy.Simulate
+  import: ghc-options-stanza
+  import: ghc2024-stanza
+  hs-source-dirs: src
+  build-depends:
+    adjunctions >=4.0 && <4.5,
+    base >=4.14 && <5,
+    containers >=0.6 && <0.9,
+    harpie >=0.1 && <0.2,
+    harpie-numhask >=0.1 && <0.2,
+    mwc-probability >=2.3.1 && <2.4,
+    numhask >=0.11 && <0.14,
+    primitive >=0.7.2 && <0.10,
+    profunctors >=5.6.2 && <5.7,
+    tdigest >=0.2.1 && <0.4,
+    text >=1.2 && <2.2,
+    vector >=0.12.3 && <0.14,
+    vector-algorithms >=0.8.0 && <0.10,
 
+  exposed-modules:
+    Data.Mealy
+    Data.Mealy.Quantiles
+    Data.Mealy.Simulate
+
 test-suite doctests
-    import: ghc2021-stanza
-    main-is: doctests.hs
-    hs-source-dirs: test
-    build-depends:
-        , base             >=4.14 && <5
-        , doctest-parallel >=0.3 && <0.4
-        , mealy
-    ghc-options: -threaded
-    type: exitcode-stdio-1.0
+  import: ghc2024-stanza
+  main-is: doctests.hs
+  hs-source-dirs: test
+  build-depends:
+    base >=4.14 && <5,
+    doctest-parallel >=0.3 && <0.5,
+    mealy,
+
+  ghc-options: -threaded
+  type: exitcode-stdio-1.0
+
+common ghc-options-exe-stanza
+  ghc-options:
+    -fforce-recomp
+    -funbox-strict-fields
+    -rtsopts
+    -threaded
+    -with-rtsopts=-N
+
+executable mealy-perf
+  import: ghc-options-exe-stanza
+  import: ghc-options-stanza
+  import: ghc2024-stanza
+  main-is: mealy-perf.hs
+  hs-source-dirs: test
+  build-depends:
+    base >=4.7 && <5,
+    clock >=0.8 && <0.9,
+    containers >=0.6 && <0.9,
+    deepseq >=1.4.4 && <1.6,
+    formatn >=0.2.1 && <0.4,
+    harpie >=0.1 && <0.2,
+    harpie-numhask >=0.1 && <0.2,
+    mealy,
+    mtl >=2.2.2 && <2.4,
+    optics-core >=0.4 && <0.5,
+    optparse-applicative >=0.17 && <0.20,
+    perf >=0.14 && <0.15,
+    tdigest >=0.2.1 && <0.4,
+    text >=1.2 && <2.2,
+    time >=1.10 && <1.15,
+
+  ghc-options: -O2
diff --git a/readme.org b/readme.org
--- a/readme.org
+++ b/readme.org
@@ -1,6 +1,6 @@
 #+TITLE: mealy
 
-[[https://hackage.haskell.org/package/mealy][file:https://img.shields.io/hackage/v/mealy.svg]] [[https://github.com/tonyday567/mealy/actions?query=workflow%3Ahaskell-ci][file:https://github.com/tonyday567/mealy/workflows/haskell-ci/badge.svg]]
+[[https://hackage.haskell.org/package/mealy][file:https://img.shields.io/hackage/v/mealy.svg]] [[https://github.com/tonyday567/mealy/actions/workflows/haskell-ci.yml][file:https://github.com/tonyday567/mealy/actions/workflows/haskell-ci.yml/badge.svg]]
 
 A 'Mealy' is a triple of functions
 
diff --git a/src/Data/Mealy.hs b/src/Data/Mealy.hs
--- a/src/Data/Mealy.hs
+++ b/src/Data/Mealy.hs
@@ -64,7 +64,6 @@
 import Data.Sequence (Seq)
 import Data.Sequence qualified as Seq
 import Data.Text (Text)
-import Data.Typeable (Typeable)
 import GHC.TypeLits
 import Harpie.Fixed qualified as F
 import Harpie.NumHask qualified as N
@@ -100,7 +99,7 @@
 -- >>> xsp <- rvsp g 10000 0.8
 
 newtype MealyError = MealyError {mealyErrorMessage :: Text}
-  deriving (Show, Typeable)
+  deriving (Show)
 
 instance Exception MealyError
 
diff --git a/src/Data/Mealy/Quantiles.hs b/src/Data/Mealy/Quantiles.hs
--- a/src/Data/Mealy/Quantiles.hs
+++ b/src/Data/Mealy/Quantiles.hs
@@ -7,6 +7,11 @@
     quantiles,
     digitize,
     signalize,
+    OnlineTDigest (..),
+    emptyOnlineTDigest,
+    onlineInsert,
+    onlineCompress,
+    onlineForceCompress,
   )
 where
 
diff --git a/test/mealy-perf.hs b/test/mealy-perf.hs
new file mode 100644
--- /dev/null
+++ b/test/mealy-perf.hs
@@ -0,0 +1,101 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | performance measurement
+module Main where
+
+import Control.Category (id)
+import Control.Monad
+import Data.List (intercalate)
+import Data.Map.Strict (Map)
+import Data.Maybe
+import Data.Mealy
+import Data.Mealy.Quantiles
+import Data.Mealy.Simulate
+import Data.TDigest hiding (median)
+import Data.Text (Text)
+import Options.Applicative
+import Perf
+import Prelude hiding (id)
+
+data Run = RunStats | RunQuantiles [Double] deriving (Eq, Show)
+
+data AppConfig = AppConfig
+  { appReportOptions :: ReportOptions,
+    appRun :: Run
+  }
+  deriving (Eq, Show)
+
+parseRun :: Parser Run
+parseRun =
+  flag' RunStats (long "stats" <> help "run stats test")
+    <|> flag' (RunQuantiles [0.1, 0.5, 0.9]) (long "quantiles" <> help "run quantiles test")
+    <|> pure RunStats
+
+parseAppConfig :: Parser AppConfig
+parseAppConfig =
+  AppConfig
+    <$> parseReportOptions defaultReportOptions
+    <*> parseRun
+
+appInfo :: ParserInfo AppConfig
+appInfo =
+  info
+    (parseAppConfig <**> helper)
+    (fullDesc <> progDesc "mealy performance measurement")
+
+main :: IO ()
+main = do
+  o <- execParser appInfo
+  let repOptions = appReportOptions o
+  let n = reportN repOptions
+  let s = reportStatDType repOptions
+  let mt = reportMeasureType repOptions
+  let run = appRun o
+  let l = reportLength repOptions
+  gen <- create
+  _ <- warmup 100
+  case run of
+    RunStats -> do
+      xs <- rvs gen l
+      reportMain ExampleSum repOptions (intercalate "-" [show run, show n, show l, show s, show mt]) (void . stats xs)
+    RunQuantiles qs -> do
+      xs <- rvs gen l
+      reportMain ExampleSum repOptions (intercalate "-" [show run, show n, show l, show s, show mt]) (void . perfQuantiles xs qs)
+
+reportRaw :: ReportOptions -> PerfT IO [[Double]] a -> IO (a, Map Text [[Double]])
+reportRaw o t = do
+  let !n = reportN o
+  let c = reportClock o
+  let mt = reportMeasureType o
+  runPerfT (measureDs mt c n) t
+
+stats :: (Semigroup t) => [Double] -> Int -> PerfT IO t [[Double]]
+stats xs l = do
+  r1 <- ffap "stats" (scan ((,) <$> ma 0.99 <*> std 0.99)) (take l xs)
+  r2 <- ffap "ma" (scan (ma 0.99)) xs
+  r3 <- ffap "std" (scan (std 0.99)) xs
+  pure [fst <$> r1, snd <$> r1, r2, r3]
+
+perfQuantiles :: (Semigroup t) => [Double] -> [Double] -> Int -> PerfT IO t [Int]
+perfQuantiles qs xs l = do
+  r1 <- ffap "digitize" (scan (digitize 0.99 qs)) (take l xs)
+  r2 <- ffap "digitize'" (scan (digitize' 0.99 qs)) (take l xs)
+  pure (r1 <> r2)
+
+digitize' :: Double -> [Double] -> Mealy Double Int
+digitize' r qs = M inject step' extract
+  where
+    step' (x, _) a = (onlineInsert a x, a)
+    inject a = (onlineInsert a (emptyOnlineTDigest r), a)
+    extract (x, l) = bucket' qs' l
+      where
+        qs' = fromMaybe (0 / 0) . (`quantile` t) <$> qs
+        (OnlineTDigest t _ _) = onlineCompress x
+        bucket' xs l' =
+          fold (M id (+) id) $
+            ( \x' ->
+                if x' > l'
+                  then 0
+                  else 1
+            )
+              <$> xs
