An alternative would be to mark both functions as NOINLINE, which the Simplifier will adhere to.
You might also want to have `countA` and `countB` close over a local variable in order for them not to be floated to the top-level.
If top-level bindings aren't an issue for you, you could simply use mutually recursive even/odd definitions.
Otherwise, something like this might do:
foo :: Bool -> Int -> Bool
foo b n
| n > 10 = even n
| otherwise = odd n
where
even 0 = b
even n = odd (n-1)
{-# NOINLINE even #-}
odd 0 = b
odd n = even (n-1)
{-# NOINLINE odd #-}
GHC 8.10 will simply duplicate both functions into each branch, but GHC master produces irreducible control flow for me:
Lib.$wfoo
= \ (b_sTr :: Bool) (ww_sTu ::
GHC.Prim.Int#) ->
joinrec {
$wodd_sTi [InlPrag=NOINLINE] ::
GHC.Prim.Int# -> Bool
[LclId[JoinId(1)], Arity=1, Str=<1L>, Unf=OtherCon []]
$wodd_sTi (ww1_sTf ::
GHC.Prim.Int#)
= case ww1_sTf of wild_X1 {
__DEFAULT -> jump $weven_sTp (GHC.Prim.-# wild_X1 1#);
0# -> b_sTr
};
$weven_sTp [InlPrag=NOINLINE, Occ=LoopBreaker]
::
GHC.Prim.Int# -> Bool
[LclId[JoinId(1)], Arity=1, Str=<1L>, Unf=OtherCon []]
$weven_sTp (ww1_sTm ::
GHC.Prim.Int#)
= case ww1_sTm of wild_X1 {
__DEFAULT -> jump $wodd_sTi (GHC.Prim.-# wild_X1 1#);
0# -> b_sTr
}; } in
case GHC.Prim.># ww_sTu 10# of {
__DEFAULT -> jump $wodd_sTi ww_sTu;
1# -> jump $weven_sTp ww_sTu
}
Cheers,
Sebastian