data IOState a b = IOState ( a -> IO (a, b) )
instance Monad (IOState a) where
return v = IOState ( \s -> return (s, v))
IOState f1 >>= f2
= IOState ( \st1 -> do (st2, r) <- f1 st1
let (IOState trans ) = f2 r in
trans st2 )
readState :: IOState a a
readState = IOState (\st -> return (st, st) )
writeState :: a -> IOState a ()
writeState s = IOState (\_ -> return ( s, () ))
readState
und writeState
ist zu beachten, daß das return
zu
dem IO-Monad gehört.
liftIO
fügt eine Berechnung in dem IO-Monad in das IOState-Monad ein.
liftIO :: IO b -> IOState a b
liftIO ioa = IOState ( \s -> do a <- ioa
return (s, a) )
extractIO :: a -> IOState a b -> IO b
extractIO init (IOState f)
= do ( st, res ) <- f init
return res
> foo x = do
> writeState x
> while ( do { nr <- readState; return (nr /= 1) } ) ( do
> nr <- readState
> liftIO (putStrLn (show nr))
> let nr´ = if ( nr ´mod´ 2 == 0 ) then (nr ´div´ 2)
> else (3 * nr + 1)
> writeState nr´
> return ()
> )
> extractIO 0 ( foo 10 )