concrete functor and monad transformers

#99SelectT not productive for most base monads

While the Hedges paper that is the origin of Control.Monad.Trans.Select explicitly mentions the (sequence.repeat) construction, it seems for most base monads this yields divergent code. Minimal example:

import Control.Monad (guard)
type K = SelectT () Maybe
zeroes = sequenceA (repeat (pure 0 :: K Int))
diverges = fmap (take 2) $ runSelectT zeroes (guard.const True)

I tested this both with the SelectT implementation of the latest transformers package and with the original implementation in the Hedges paper. Thus it is not the fault of the library implementation, but at the least unintended and undocumented behaviour. I reached out to Jules Hedges for comment.

I suspect the cause is strictness of the base monad's bind. With Identity as the base monad, sequence.repeat constructions are indeed productive.

  • It seems the issue is * sequence.repeat is not productive with strict monads, and * SelectT r m is strict if and only if m is.

  • Indeed that seems to be the cause. Since by virtue of lift the strictness of the base monad is likely preserved by any transformer, we can not expect SelectT r m to perform better than m. Does the transformers package have any policy regarding strictness analysis? I feel we should at least add a warning in the Haddocks, since infinite lists were one of the showcases in the Hedges paper.