Data-first recursive consumers in readBytes

Reorder recursive byte-stream consumers so the consumed input is inspected
before loop-control arguments can drive evaluation. Previously, partially
applying `readBytes` to a known count, such as `readBytes 2`, allowed the
evaluator to specialize the recursive worker using known counter values
while the byte stream was still abstract. This caused symbolic recursion
over unknown input and produced an enormous normal form.

The recursive worker now takes the byte stream first and immediately
case-analyzes it. As a result, partial application blocks at the input
boundary instead of unrolling the counter loop.

This preserves the fully-applied behavior of `readBytes`, while making partial
application such as `readBytes 2` normalize safely.
This commit is contained in:
2026-05-07 10:07:43 -05:00
parent 37d57044e2
commit e8ab61dbaa
5 changed files with 319 additions and 47 deletions

View File

@@ -21,21 +21,6 @@
tricuPackage =
haskellPackages.callCabal2nix packageName self {};
tricuTests =
hsLib.overrideCabal tricuPackage (old: {
doCheck = true;
configureFlags = (old.configureFlags or []) ++ [
"--enable-tests"
];
checkPhase = ''
runHook preCheck
./Setup test tricu-tests --show-details=direct
runHook postCheck
'';
});
customGHC = haskellPackages.ghcWithPackages (hpkgs: with hpkgs; [
megaparsec
]);
@@ -43,10 +28,8 @@
packages.${packageName} = tricuPackage;
packages.default = tricuPackage;
packages.test = tricuTests;
checks.${packageName} = tricuTests;
checks.default = tricuTests;
checks.${packageName} = tricuPackage;
checks.default = tricuPackage;
defaultPackage = self.packages.${system}.default;