How to use the delivery monad to create a function that generates globally unique names?

History:

I am running a code translation project that requires me to generate variable names. None of the names that I generate should duplicate each other.

I'm really upset, as that would be stupidly simple and elegant with the Python generator function.

What I tried:

The way I did this before was to pass the counter variable down through recursive calls to my translation code and pass the (possibly increased) counter back to the return value of basically every function.

It was really dirty: he added an additional parameter to track each of these functions; and, even worse, it made me work with messy return values ​​of tuples, where otherwise I would have a simple unary return value.

I never understood monads in a short time with Haskell, but I had a suspicion that I could use a wrapper in a monad Stateto simulate a global counter variable. After 3 days of turmoil, trying to rip out the monads and make one of my own, and then try to change someone else's monads to generate the values ​​I need, I finally resigned myself to using someone else at a high level monad ( perhaps with a few changes.)

My problem now:

MonadSupply MonadUnique , , , , . , , .

, MonadSupply :

runSupplyVars x = runSupply x vars
    where vars = [replicate k ['a'..'z'] | k <- [1..]] >>= sequence

, ! , :

> :t runSupplyVars
runSupplyVars :: Supply [Char] a -> Identity (a, [[Char]])

() , . , , , . .

:

- runSupplyVars?

, ? , , .

+4
1

Supply, do Supply, .

, var_, , - :

newVar :: Supply [Char] [Char]
newVar = do
    name <- supply
    return ("var"_++name)

Supply, runSupplyVars , .

, runIdentity Control.Monad.Identity, runSupplyVars (a, [[Char]]), , () . , runSupplyVars, :

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

, . , do - IO main, Supply [Char] realProgram , , :

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
+6

Source: https://habr.com/ru/post/1534758/


All Articles