, 당신은
import Data.IORef
import Control.Monad ((=<<))
type IntGen = IORef Int
intGen :: IO IntGen
intGen = newIORef 1
next :: IntGen -> IO Int
next gen = do
val <- readIORef gen
writeIORef gen $ val + 1
return val
main :: IO()
main = do
integer <- intGen
-- f =<< m == m >>= f
print =<< next integer
print =<< next integer
print =<< next integer
처럼 뭔가를 할 수 아니면 순수하게이 작업을 수행 할 State
모나드를 사용할 수 있습니다 : 두 번째에서
import Control.Monad.State
next :: Monad m => StateT Int m Int
next = do
val <- get
put $ val + 1
return val
app :: StateT Int IO()
app = do
let stprint = liftIO . print
stprint =<< next
stprint =<< next
stprint =<< next
main :: IO()
main = void $ runStateT app 1
을 초기 값은 1
입니다 runStateT
에 제공되므로 다른 값에서 시작할 수 있다는 점에서보다 유연합니다.
일반적으로 느리게 생성 된 정수 값이 필요할 때 목록이 이동하는 방법입니다. 예를 들어, 내가
def processFile(directory):
integer = intGen()
for fname in os.listdir(directory):
full_fname = os.path.join(directory, fname)
if os.path.isfile(full_fname):
i = next(integer)
new_fname = '{}-{}'.format(i, fname)
os.rename(full_fname, os.path.join(directory, new_fname))
같은 것을 가질 수 있지만 하스켈에서 내가
import Control.Monad
import System.Directory
import System.FilePath
processFiles :: FilePath -> IO()
processFiles directory = do
contents <- getDirectoryContents directory
files <- filterM doesFileExist $ map (directory </>) contents
forM_ (zip [1..] files) $ \(i, fname) -> do
let newFName = show i ++ "-" ++ fname
renameFile (directory </> fname) (directory </> newFName)
보통 하나가 바로'[1 ..]'같은 것을 사용하고 그 위에지도 것은 다른 값을 압축, 또는 인덱스를 이후 당신의'intGen'은 기본적으로 1에서 시작하는 게으른 무한한 정수리스트와 같습니다. 당신은 상태 모나드를 사용할 수 있습니다,하지만 나는 그것이 과도 할 것이라고 생각합니다. 당신의 '다음'사용은 가변적 인 상태를 의미합니다. 그리고 당신은 국가 모나드로 그것을 할 수 있습니다. 만약 당신이 IO 모나드에서 그것을 원한다면 IORefs를 사용할 수 있습니다. 정말 응용 프로그램에 따라 다릅니다. – bheklilr
이것은 X/Y 문제처럼 보입니다. 달성하고자하는 최종 목표는 무엇입니까? 나는 두 번째 @bheklilr; 아마도이를 수행하는 일반적인 방법은 정수의 무한한 목록을 반환하는 함수 하나와 그 목록을 소비하고 그 함수를 사용하는 함수를 갖는 것입니다. 전체 프로그램이 의미하는 바를 모른 채 말하기는 어렵습니다. – MathematicalOrchid