This blog post has an interesting explanation of how to use the Omega monad to enumerate an arbitrary grammar diagonally. He offers an example of how to do so, resulting in
My first ugly approach was:
allTerms :: Omega T
allTerms = do
which <- each [ 1,2,3 ]
if which == 1 then
return A
else if which == 2 then do
x <- allTerms
return $ B x
else do
x <- allTerms
y <- allTerms
return $ C x y
But then, after some cleaning up I reached this one liner
import Control.Applicative
import Control.Monad.Omega
import Control.Monad
allTerms :: Omega T
allTerms = join $ each [return A, B <$> allTerms, C <$> allTerms <*> allTerms]
Note that order matters: return A has to be the first choice in the list above, or allTerms will not terminate. Basically, the Omega monad ensures a "fair scheduling" among choices, saving you from e.g. infiniteList ++ something, but does not prevent infinite recursion.
An even more elegant solution was suggested by Crazy FIZRUK, exploiting the
Alternative instance of Omega.
import Control.Applicative
import Data.Foldable (asum)
import Control.Monad.Omega
allTerms :: Omega T
allTerms = asum [ pure A
, B <$> allTerms
, C <$> allTerms <*> allTerms
]