On a tangent, not doing IO, but food for thought: {-# LANGUAGE FlexibleContexts #-} import Control.Monad.State.Lazy as N import Control.Monad.State.Strict as S gen :: (MonadState [()] m) => m () gen = do gen modify (() :) many = take 3 (N.execState gen []) none = take 3 (S.execState gen [])