To actually use the Supply
monad you should structure your code with do
notation and call the supply
function when you actually need a name.
For example, this will produce a new variable name prefixed with var_
, just to show how you might get something from the supply and use it:
newVar :: Supply [Char] [Char]
newVar = do
name <- supply
return ("var"_++name)
You'll need to structure your whole program around the Supply
monad and then only call runSupplyVars
once at the top-level, otherwise different parts of the program will have independent supplies and so might reuse the same variable name.
Finally, you'll need runIdentity
from Control.Monad.Identity
to unpack the result of runSupplyVars
into the underlying tuple of type (a, [[Char]])
, and then throw away the second value which is just the (infinite) list of unused names. You might be better off redefining runSupplyVars
to do this for you:
import Control.Monad.Identity
[...]
runSupplyVars :: Supply [Char] a -> a
runSupplyVars x = fst (runIdentity (runSupply x vars))
where vars = [replicate k ['a'..'z'] | k <- [1..]] >>= sequence
Here's a more complete example putting it all together. Note the different monads with which do
notation is used - IO
for the main
function, and Supply [Char]
for realProgram
and probably most of the rest of the code in a bigger version:
import MonadSupply
import Control.Monad.Identity
main :: IO ()
main = do
let result = runSupplyVars realProgram
print result
realProgram :: Supply [Char] Int
realProgram = do
x <- newVar
return 0
newVar :: Supply [Char] [Char]
newVar = do
name <- supply
return ("var_"++name)
runSupplyVars :: Supply [Char] a -> a
runSupplyVars x = fst (runIdentity (runSupply x vars))
where vars = [replicate k ['a'..'z'] | k <- [1..]] >>= sequence