I’m sorry if I interrupted the discussion.
Essentially, yes. The reason is that GHC’s delimited continuation primops require the IO monad to execute them. In my design approach, libraries like fused-effects
, polysemy
, and freer-simple
allow using any monad as the base monad. This isolates the semantics from the IO level, preventing users from falling into pitfalls caused by leaky abstractions from the IO layer. Relying on the IO monad would eliminate this property, which is a major concern for me.
Additionally, the situation is somewhat more complex and relates to the actual performance of primops. Benchmark results for the eff
library, which utilizes primops for optimization, raise questions about the true speed benefits of primops. Specifically, effects like NonDet and Coroutine exhibit O(n²) level slowness. However, this may be due to the implementation of eff
rather than the primops themselves.
During the performance improvement process for Heftia, I first forked a library called speff
to prototype an IO-based version of Heftia (which also does not use primops). While it worked and was very fast in some cases, it couldn’t resolve the poor performance compatibility with higher-order effects (such as the catch.10000.sp_modified_for_non_scoped_resumption_support
benchmark). Given the issues with eff
, I didn’t think using primops would help solve this problem, especially since primops typically offer only about a 2x speedup.
Therefore, I changed my approach and optimized based on Freer using freer-simple
, achieving practical speeds. This demonstrated that not only for semantic reasons but also for performance compatibility, Freer was a better fit. Consequently, Freer was adopted.