Thanks, indeed the exposed bits are enough to implement
findBA :: a -> ByteArray -> New.RadixTree a -> a
findBA d key = \(New.RadixTree maybeX tree) -> case keyLen of
0 -> fromMaybe d maybeX
_ -> go 0 tree
where
keyLen = sizeofByteArray key
go !n = \case
New.Bin p l r -> go n (if indexByteArray key n < p then l else r)
New.Tip arr@(sizeofByteArray -> arrLen) mx dx
| arrLen + n <= keyLen
, EQ <- compareByteArrays key n arr 0 arrLen
-> if arrLen + n == keyLen then fromMaybe d mx else go (n + arrLen) dx
| otherwise
-> d
New.Nil -> d
The benchmarks for long (tenfold) common prefixes are quite impressive:
Old: OK
1.99 ms ± 109 μs
New: OK
3.03 ms ± 216 μs
findBA: OK
980 μs ± 54 μs
However, with shorter common prefixes findBA
is measurably slower than other implementations:
Old: OK
600 μs ± 14 μs
New: OK
656 μs ± 15 μs
findBA: OK
693 μs ± 26 μs
Upd.: It is possible though to use compareByteArrays
only if prefix length is, say, 8 or more, in which case we would reap the best of both worlds.