diff --git a/flatparse.cabal b/flatparse.cabal
--- a/flatparse.cabal
+++ b/flatparse.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.36.0.
+-- This file has been generated from package.yaml by hpack version 0.37.0.
 --
 -- see: https://github.com/sol/hpack
 
 name:           flatparse
-version:        0.5.1.0
+version:        0.5.1.1
 synopsis:       High-performance parsing from strict bytestrings
 description:    @Flatparse@ is a high-performance parsing library for strict bytestring input. See the README for more information:
                 <https://github.com/AndrasKovacs/flatparse>.
@@ -25,6 +25,8 @@
   , GHC == 9.0.2
   , GHC == 9.2.5
   , GHC == 9.4.4
+  , GHC == 9.6.6
+  , GHC == 9.8.3
 extra-source-files:
     README.md
 
diff --git a/src/FlatParse/Basic.hs b/src/FlatParse/Basic.hs
--- a/src/FlatParse/Basic.hs
+++ b/src/FlatParse/Basic.hs
@@ -92,6 +92,7 @@
   , FP.Base.try
   , FP.Base.err
   , FP.Base.withError
+  , FP.Base.withAnyResult
   , FP.Base.fails
   , FP.Base.cut
   , FP.Base.cutting
@@ -157,6 +158,9 @@
 
   ) where
 
+-- for WORDS_BIGENDIAN
+#include "MachDeps.h"
+
 import FlatParse.Basic.Parser
 import FlatParse.Basic.Base
 import FlatParse.Basic.Integers
@@ -395,7 +399,7 @@
         _      -> error "FlatParse.Basic.validPos: got a non-OK result, impossible"
 {-# inline validPos #-}
 
--- | Compute corresponding line and column numbers for each `Pos` in a list,
+-- | Compute corresponding line and column numbers (both starting from 0) for each `Pos` in a list,
 --   assuming UTF8 encoding. Throw an error on invalid positions. Note:
 --   computing lines and columns may traverse the `B.ByteString`, but it
 --   traverses it only once regardless of the length of the position list.
@@ -494,7 +498,7 @@
             -- reading could probably segfault
             go8 fp eob s0 st s
           _  -> -- >= 8 bytes of input: use efficient 8-byte scanning
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
             -- big-endian ("L->R"): find leftmost null byte
             let !x@(I# x#) = Common.zbytel'intermediate (I# (indexIntOffAddr# s 0#)) in
 #else
@@ -504,7 +508,7 @@
             case x# ==# 0# of
               1# -> go fp eob s0 st sWord -- no 0x00 in next word
               _  -> -- 0x00 somewhere in next word
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
                 let !(I# nullIdx#) = Common.zbytel'toIdx x in
 #else
                 let !(I# nullIdx#) = Common.zbyter'toIdx x in
diff --git a/src/FlatParse/Basic/Base.hs b/src/FlatParse/Basic/Base.hs
--- a/src/FlatParse/Basic/Base.hs
+++ b/src/FlatParse/Basic/Base.hs
@@ -41,6 +41,7 @@
   , try
   , err
   , withError
+  , withAnyResult
   , fails
   , cut
   , cutting
@@ -79,6 +80,21 @@
     ParserT g -> g fp eob s st'
   x -> x
 {-# inline withError #-}
+
+-- | Run the parser, and handle each possible result.
+withAnyResult
+  :: ParserT st t a         -- ^ The parser to run.
+  -> (a -> ParserT st e b)  -- ^ The parser to run in case of success.
+  -> ParserT st e b         -- ^ The parser to run in case of failure.
+  -> (t -> ParserT st e b)  -- ^ The parser to run in case of error.
+  -> ParserT st e b
+withAnyResult (ParserT first) whenSuccess (ParserT whenFailure) whenError =
+  ParserT \fp eob n st ->
+    case first fp eob n st of
+      OK# st' a  n' -> runParserT# (whenSuccess a) fp eob n' st'
+      Fail# st'     -> whenFailure fp eob n st'
+      Err# st' e    -> runParserT# (whenError e) fp eob n st'
+{-# INLINE withAnyResult #-}
 
 -- | Convert a parsing error into failure.
 try :: ParserT st e a -> ParserT st e a
diff --git a/src/FlatParse/Basic/Integers.hs b/src/FlatParse/Basic/Integers.hs
--- a/src/FlatParse/Basic/Integers.hs
+++ b/src/FlatParse/Basic/Integers.hs
@@ -36,6 +36,9 @@
   , sizedUnsafe#
   ) where
 
+-- for WORDS_BIGENDIAN
+#include "MachDeps.h"
+
 import FlatParse.Basic.Parser
 import FlatParse.Basic.Base ( withEnsure# )
 
@@ -204,7 +207,7 @@
 
 -- | Parse any 'Word16' (little-endian).
 anyWord16le :: ParserT st e Word16
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord16le = withAnyWord16 (pure . byteSwap16)
 #else
 anyWord16le = anyWord16
@@ -213,7 +216,7 @@
 
 -- | Parse any 'Word16' (big-endian).
 anyWord16be :: ParserT st e Word16
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord16be = anyWord16
 #else
 anyWord16be = withAnyWord16 (pure . byteSwap16)
@@ -222,7 +225,7 @@
 
 -- | Parse any 'Word32' (little-endian).
 anyWord32le :: ParserT st e Word32
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord32le = withAnyWord32 (pure . byteSwap32)
 #else
 anyWord32le = anyWord32
@@ -231,7 +234,7 @@
 
 -- | Parse any 'Word32' (big-endian).
 anyWord32be :: ParserT st e Word32
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord32be = anyWord32
 #else
 anyWord32be = withAnyWord32 (pure . byteSwap32)
@@ -240,7 +243,7 @@
 
 -- | Parse any 'Word64' (little-endian).
 anyWord64le :: ParserT st e Word64
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord64le = withAnyWord64 (pure . byteSwap64)
 #else
 anyWord64le = anyWord64
@@ -249,7 +252,7 @@
 
 -- | Parse any 'Word64' (big-endian).
 anyWord64be :: ParserT st e Word64
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord64be = anyWord64
 #else
 anyWord64be = withAnyWord64 (pure . byteSwap64)
@@ -258,7 +261,7 @@
 
 -- | Parse any 'Int16' (little-endian).
 anyInt16le :: ParserT st e Int16
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt16le = withAnyWord16 (pure . word16ToInt16 . byteSwap16)
 #else
 anyInt16le = anyInt16
@@ -267,7 +270,7 @@
 
 -- | Parse any 'Int16' (big-endian).
 anyInt16be :: ParserT st e Int16
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt16be = anyInt16
 #else
 anyInt16be = withAnyWord16 (pure . word16ToInt16 . byteSwap16)
@@ -276,7 +279,7 @@
 
 -- | Parse any 'Int32' (little-endian).
 anyInt32le :: ParserT st e Int32
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt32le = withAnyWord32 (pure . word32ToInt32 . byteSwap32)
 #else
 anyInt32le = anyInt32
@@ -285,7 +288,7 @@
 
 -- | Parse any 'Int32' (big-endian).
 anyInt32be :: ParserT st e Int32
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt32be = anyInt32
 #else
 anyInt32be = withAnyWord32 (pure . word32ToInt32 . byteSwap32)
@@ -294,7 +297,7 @@
 
 -- | Parse any 'Int64' (little-endian).
 anyInt64le :: ParserT st e Int64
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt64le = withAnyWord64 (pure . word64ToInt64 . byteSwap64)
 #else
 anyInt64le = anyInt64
@@ -303,7 +306,7 @@
 
 -- | Parse any 'Int64' (big-endian).
 anyInt64be :: ParserT st e Int64
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt64be = anyInt64
 #else
 anyInt64be = withAnyWord64 (pure . word64ToInt64 . byteSwap64)
diff --git a/src/FlatParse/Examples/BasicLambda/Lexer.hs b/src/FlatParse/Examples/BasicLambda/Lexer.hs
--- a/src/FlatParse/Examples/BasicLambda/Lexer.hs
+++ b/src/FlatParse/Examples/BasicLambda/Lexer.hs
@@ -67,7 +67,9 @@
       pos      = case e of Imprecise pos e -> pos
                            Precise pos e   -> pos
       ls       = FP.linesUtf8 b
-      (l, c)   = head $ FP.posLineCols b [pos]
+      (l, c)   = case FP.posLineCols b [pos] of
+                   x: _ -> x
+                   _    -> error "impossible"
       line     = if l < length ls then ls !! l else ""
       linum    = show l
       lpad     = map (const ' ') linum
diff --git a/src/FlatParse/Stateful.hs b/src/FlatParse/Stateful.hs
--- a/src/FlatParse/Stateful.hs
+++ b/src/FlatParse/Stateful.hs
@@ -101,6 +101,7 @@
   , FP.Base.try
   , FP.Base.err
   , FP.Base.withError
+  , FP.Base.withAnyResult
   , FP.Base.fails
   , FP.Base.cut
   , FP.Base.cutting
@@ -166,6 +167,8 @@
 
   ) where
 
+-- for WORDS_BIGENDIAN
+#include "MachDeps.h"
 
 import qualified FlatParse.Basic as Basic
 import FlatParse.Stateful.Parser
@@ -472,7 +475,7 @@
             -- reading could probably segfault
             go8 fp r n eob s0 st s
           _  -> -- >= 8 bytes of input: use efficient 8-byte scanning
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
             -- big-endian ("L->R"): find leftmost null byte
             let !x@(I# x#) = Common.zbytel'intermediate (I# (indexIntOffAddr# s 0#)) in
 #else
@@ -482,7 +485,7 @@
             case x# ==# 0# of
               1# -> go fp r n eob s0 st sWord -- no 0x00 in next word
               _  -> -- 0x00 somewhere in next word
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
                 let !(I# nullIdx#) = Common.zbytel'toIdx x in
 #else
                 let !(I# nullIdx#) = Common.zbyter'toIdx x in
diff --git a/src/FlatParse/Stateful/Base.hs b/src/FlatParse/Stateful/Base.hs
--- a/src/FlatParse/Stateful/Base.hs
+++ b/src/FlatParse/Stateful/Base.hs
@@ -41,6 +41,7 @@
   , try
   , err
   , withError
+  , withAnyResult
   , fails
   , cut
   , cutting
@@ -79,6 +80,21 @@
     ParserT g -> g fp r eob s n st'
   x -> x
 {-# inline withError #-}
+
+-- | Run the parser, and handle each possible result.
+withAnyResult
+  :: ParserT st r t a         -- ^ The parser to run.
+  -> (a -> ParserT st r e b)  -- ^ The parser to run in case of success.
+  -> ParserT st r e b         -- ^ The parser to run in case of failure.
+  -> (t -> ParserT st r e b)  -- ^ The parser to run in case of error.
+  -> ParserT st r e b
+withAnyResult (ParserT first) whenSuccess (ParserT whenFailure) whenError =
+  ParserT \fp !r eob s n st ->
+    case first fp r eob s n st of
+      OK# st' a s' n' -> runParserT# (whenSuccess a) fp r eob s' n' st'
+      Fail# st'       -> whenFailure fp r eob s n st'
+      Err# st' e      -> runParserT# (whenError e) fp r eob s n st'
+{-# INLINE withAnyResult #-}
 
 -- | Convert a parsing error into failure.
 try :: ParserT st r e a -> ParserT st r e a
diff --git a/src/FlatParse/Stateful/Integers.hs b/src/FlatParse/Stateful/Integers.hs
--- a/src/FlatParse/Stateful/Integers.hs
+++ b/src/FlatParse/Stateful/Integers.hs
@@ -36,6 +36,9 @@
   , sizedUnsafe#
   ) where
 
+-- for WORDS_BIGENDIAN
+#include "MachDeps.h"
+
 import FlatParse.Stateful.Parser
 import FlatParse.Stateful.Base ( withEnsure# )
 
@@ -206,7 +209,7 @@
 
 -- | Parse any 'Word16' (little-endian).
 anyWord16le :: ParserT st r e Word16
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord16le = withAnyWord16 (pure . byteSwap16)
 #else
 anyWord16le = anyWord16
@@ -215,7 +218,7 @@
 
 -- | Parse any 'Word16' (big-endian).
 anyWord16be :: ParserT st r e Word16
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord16be = anyWord16
 #else
 anyWord16be = withAnyWord16 (pure . byteSwap16)
@@ -224,7 +227,7 @@
 
 -- | Parse any 'Word32' (little-endian).
 anyWord32le :: ParserT st r e Word32
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord32le = withAnyWord32 (pure . byteSwap32)
 #else
 anyWord32le = anyWord32
@@ -233,7 +236,7 @@
 
 -- | Parse any 'Word32' (big-endian).
 anyWord32be :: ParserT st r e Word32
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord32be = anyWord32
 #else
 anyWord32be = withAnyWord32 (pure . byteSwap32)
@@ -242,7 +245,7 @@
 
 -- | Parse any 'Word64' (little-endian).
 anyWord64le :: ParserT st r e Word64
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord64le = withAnyWord64 (pure . byteSwap64)
 #else
 anyWord64le = anyWord64
@@ -251,7 +254,7 @@
 
 -- | Parse any 'Word64' (big-endian).
 anyWord64be :: ParserT st r e Word64
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyWord64be = anyWord64
 #else
 anyWord64be = withAnyWord64 (pure . byteSwap64)
@@ -260,7 +263,7 @@
 
 -- | Parse any 'Int16' (little-endian).
 anyInt16le :: ParserT st r e Int16
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt16le = withAnyWord16 (pure . word16ToInt16 . byteSwap16)
 #else
 anyInt16le = anyInt16
@@ -269,7 +272,7 @@
 
 -- | Parse any 'Int16' (big-endian).
 anyInt16be :: ParserT st r e Int16
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt16be = anyInt16
 #else
 anyInt16be = withAnyWord16 (pure . word16ToInt16 . byteSwap16)
@@ -278,7 +281,7 @@
 
 -- | Parse any 'Int32' (little-endian).
 anyInt32le :: ParserT st r e Int32
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt32le = withAnyWord32 (pure . word32ToInt32 . byteSwap32)
 #else
 anyInt32le = anyInt32
@@ -287,7 +290,7 @@
 
 -- | Parse any 'Int32' (big-endian).
 anyInt32be :: ParserT st r e Int32
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt32be = anyInt32
 #else
 anyInt32be = withAnyWord32 (pure . word32ToInt32 . byteSwap32)
@@ -296,7 +299,7 @@
 
 -- | Parse any 'Int64' (little-endian).
 anyInt64le :: ParserT st r e Int64
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt64le = withAnyWord64 (pure . word64ToInt64 . byteSwap64)
 #else
 anyInt64le = anyInt64
@@ -305,7 +308,7 @@
 
 -- | Parse any 'Int64' (big-endian).
 anyInt64be :: ParserT st r e Int64
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
 anyInt64be = anyInt64
 #else
 anyInt64be = withAnyWord64 (pure . word64ToInt64 . byteSwap64)
