If you want "lazily generated elements with effects", one solution is to eschew the conventional list type and use a List monad transformer, like ListT
from the pipes library:
import System.Random
import Control.Monad
import Pipes
import qualified Pipes.Prelude as P
rs :: rs :: (Random a, MonadPlus m, MonadIO m) => (a,a) -> m a
rs b = liftIO (randomRIO b) `mplus` rs b
main :: IO ()
main = runEffect $ enumerate (rs (1::Int,10)) >-> P.take 5 >-> P.print
The result is:
*Main> :main
7
2
5
6
4
However, this bars you from using the conventional list functions to consume the "effectful list"; you are thrust into the pipes ecosystem.
(Applicative folds from the foldl package can also be used to consume the list, with the impurely
and foldM
auxiliary functions.)
The MonadPlus
interface should be used as much as possible while defining effectful lists, as described here. It makes the effectful lists more library-agnostic.