Products have Problematic Strictness
I tried using gap for the product explained in your paper Composing bidirectional programs monadically but the generic function has strictness in the parameters which caused the biparser drop bp = try bp *> drop bp <!> pure () to infinitely loop.
This is also problematic in base Data.Functor.Product.Product and I have detailed the problem more thoroughly in
https://github.com/haskell/core-libraries-committee/issues/268
or
https://gitlab.haskell.org/ghc/ghc/-/issues/24898
This is probably a problem in more than just gap because I found with Product it to be a problem with
- Applicative
- Alternative
- MonadPlus
- MonadZip
- Semigroup - impossible to create infinite data structures
so it would be worth checking those generic functions as well.
Indeed, the instances for (:*:) (the GHC.Generics-specific variant of Product) are also too strict: https://hackage.haskell.org/package/ghc-internal-9.1001.0/docs/src//GHC.Internal.Generics.html#local-6989586621679638273
This can only be fixed in base.
Thanks for pointing this out. Should this issue be closed?
You can keep this open. Maybe there could be a local workaround or extra doc for this issue in generic-data while it gets resolved upstream.
I wonder how useful the product of monads/applicatives really is. In our paper on bidirectional programming we mainly chose it for simplicity of exposition, but in practice I'd much prefer an approach based on polymorphism. Rather than constructing a biparser as a pair of parser and printer, we can write it as a polymorphic function parameterized by biparser primitives and instantiate it separately to parsers and printers (and possibly more).