```module Data.CompactSequence.Internal.Numbers where
import Data.Bits

-- A representation of 1-2 binary numbers. We use this to build stacks or stack
-- fragments of known size.
data Dyadic = DOne !Dyadic | DTwo !Dyadic | DEnd
deriving (Eq, Show)

toDyadic n0 = go (n0 + 1)
where
go 1 = DEnd
go n = case n .&. 1 of
0 -> DOne \$ go (unsafeShiftR n 1)
_ -> DTwo \$ go (unsafeShiftR n 1)
{-# NOINLINE toDyadic #-}

{-
-- We'll have to figure out how to write something
-- like this to append stacks more efficiently.
incDyadic DEnd = DOne DEnd
incDyadic (DOne n) = DTwo n
incDyadic (DTwo n) = DOne (incDyadic n)

where
go 0 DEnd !n = n
go 1 DEnd !n = incDyadic n
go _ DEnd !n = incDyadic (incDyadic n)
go !c !n DEnd = go c DEnd n
go !c
-}

-- A representation of 2-3 binary numbers, where the most significant digit may
-- also be 1. We use this to build stacks or stack fragments of known size.
data Bin23 = Two23 !Bin23 | Three23 !Bin23 | End23 | OneEnd23
deriving (Eq, Show)

toBin23 :: Int -> Bin23
toBin23 n0 = go (n0 + 2)
where
go 2 = End23
go 3 = OneEnd23
go n = case n .&. 1 of
0 -> Two23 \$ go (unsafeShiftR n 1)
_ -> Three23 \$ go (unsafeShiftR n 1)
{-# NOINLINE toBin23 #-}

data Bin45 = Four45 !Bin45 | Five45 !Bin45 | End45 | OneEnd45 | TwoEnd45 | ThreeEnd45

toBin45 :: Int -> Bin45
toBin45 n0 = go (n0 + 4)
where
go 4 = End45
go 5 = OneEnd45
go 6 = TwoEnd45
go 7 = ThreeEnd45
go n = case n .&. 1 of
0 -> Four45 \$ go (unsafeShiftR n 1)
_ -> Five45 \$ go (unsafeShiftR n 1)
{-# NOINLINE toBin45 #-}
```