I found an interesting example of the lazy State monad that uses "head recursion".
I tried to adapt the example for the lazy Writer monad but it proved difficult. If you naively consume the head of the infinite accumulator, it will hang, even with the lazy version of the monad:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Control.Monad.Writer.Lazy
import Data.Monoid
lazywr :: Writer [()] ()
lazywr = lazywr >> tell [()]
-- hangs
main :: IO ()
main = putStrLn
. show
. take 1
. snd
. runWriter
$ lazywr
import Control.Monad.Writer.Lazy
import Data.Monoid
lazywr :: Writer (Dual [()]) ()
lazywr = lazywr >> tell (Dual [()])
-- works ok
main :: IO ()
main = putStrLn
. show
. take 1
. getDual
. snd
. runWriter
$ lazywr
The trick is to use Dual
from Data.Monoid
:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Control.Monad.Writer.Lazy
import Data.Monoid
lazywr :: Writer [()] ()
lazywr = lazywr >> tell [()]
-- hangs
main :: IO ()
main = putStrLn
. show
. take 1
. snd
. runWriter
$ lazywr
import Control.Monad.Writer.Lazy
import Data.Monoid
lazywr :: Writer (Dual [()]) ()
lazywr = lazywr >> tell (Dual [()])
-- works ok
main :: IO ()
main = putStrLn
. show
. take 1
. getDual
. snd
. runWriter
$ lazywr
Maybe I suffer from a failure of imagination, but I can't think of any practical problem in which the lazy Writer monad offers an advantage over the strict version.