I have a function in my main block
map anyHeavyFunction [list]
I'd like to show a progress bar during the computation process or add additional actions (pause, stop process etc.), but because map is a pure function I can't do it directly. I can guess I have to use monads, but what monad is appropriate? IO, State?
I know there is at least one library on hackage that has some pre-made monad transformers for this task, but I normally turn to the pipes package to roll my own when I need one. I am using pipes-4.0.0 it is going to be on hackage this weekend, but you can grab it form the github repo before that.
I also used terminal-progress-bar package so that it makes a nice terminal animation as well.
{-# language BangPatterns #-}
import Pipes
import qualified Pipes.Prelude as P
import Control.Monad.IO.Class
import System.ProgressBar
import System.IO ( hSetBuffering, BufferMode(NoBuffering), stdout )
-- | Takes the total size of the stream to be processed as l and the function
-- to map as fn
progress l = loop 0
where
loop n = do
liftIO $ progressBar (msg "Working") percentage 40 n l
!x <- await -- bang pattern to make strict
yield x
loop (n+1)
main = do
-- Force progress bar to print immediately
hSetBuffering stdout NoBuffering
let n = 10^6
let heavy x = last . replicate n $ x -- time wasting function
r <- P.toListM $ each [1..100] >-> P.map heavy >-> progress 100
putStrLn ""
return r
This animates:
> Working [=>.......................] 7%
> Working [=====>...................] 20%
Every update erases the last bar so it only take up one line on the terminal. Then it finishes like so:
> main
Working [=========================] 100%
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]
Here's a (kind of) simple answer that I'm not satisfied with. It is based on the fact that #shellenberg wanted to apply a heavy function on each element of a (supposedly long) list. If it suffices to move the "progress bar" once for every element of the list, then the following can be turned into a general solution.
First of all, you need to pick the monad in which you'll work. This depends on what exactly your "progress bar" is. For this discussion, let's say that the IO monad is enough and that we want to alternately display the characters -, /, | and \. You'll also (most probably) need some kind of state S (here it is only the number of elements processed so far, therefore S is Int), so the real monad used will be StateT S IO.
Suppose your original program is:
m = 100000 -- how many elements the list has
-- Your (pure) function
anyHeavyFunction :: Int -> Bool
anyHeavyFunction n =
length [1..n] + length [n+1..4217] == 4217
-- Your list
list :: [Int]
list = take m $ repeat 4217
-- The main program
main :: IO ()
main = do
let l = map anyHeavyFunction list
if and l
then putStrLn "OK"
else putStrLn "WRONG"
(Notice that, very conveniently, the heavy function takes the same time for each element of the list.)
This is how you could convert it to display the crude "progress bar":
import Control.Monad.State
import System.IO (hFlush, stdout)
m = 100000 -- how many elements the list has
k = 5000 -- how often you want to "tick"
tick :: a -> StateT Int IO a
tick x = do
s <- get
put $ s+1
when (s `mod` k == 0) $ liftIO $ do
let r = (s `div` k) `mod` 4
putChar $ "-/|\\" !! r
putChar '\b'
hFlush stdout
x `seq` return x
-- Your (pure) function
anyHeavyFunction :: Int -> Bool
anyHeavyFunction n =
length [1..n] + length [n+1..4217] == 4217
-- Your list
list :: [Int]
list = take m $ repeat 4217
-- The main program
main :: IO ()
main = do
l <- flip evalStateT 0 $ mapM (tick . anyHeavyFunction) list
if and l
then putStrLn "OK"
else putStrLn "WRONG"
An interesting point: The seq in tick forces evaluation of the result for each element of the list. This is enough, if the result has a basic type (Bool here). Otherwise, it's not clear what you would want to do -- remember Haskell is lazy!
If one wants a finer progress bar or if one is not satisfied with the assumption that one "tick" will be counted for each element of the list, then I believe it's necessary to incorporate the ticking in the logic of the heavy function. This makes it ugly... I'd like to see what kind of general solutions can be suggested to that. I'm all in for Haskell, but I think it just sucks for such things as progress bars... There's no free lunch; you can't be pure and lazy and have your progress bars made easy!
EDIT: A version which uses the ProgressBar module suggested by #Davorak. It certainly looks nicer than my rotating bar.
import Control.Monad.State
import System.ProgressBar
import System.IO (hSetBuffering, BufferMode(NoBuffering), stdout)
m = 100000 -- how many elements the list has
k = 5000 -- how often you want to "tick"
tick :: a -> StateT Int IO a
tick x = do
s <- get
put $ s+1
when (s `mod` k == 0) $ liftIO $ do
progressBar (msg "Working") percentage 40 (toInteger s) (toInteger m)
x `seq` return x
-- Your (pure) function
anyHeavyFunction :: Int -> Bool
anyHeavyFunction n =
length [1..n] + length [n+1..4217] == 4217
-- Your list
list :: [Int]
list = take m $ repeat 4217
-- The main program
main :: IO ()
main = do
hSetBuffering stdout NoBuffering
l <- flip evalStateT 0 $ mapM (tick . anyHeavyFunction) list
if and l
then putStrLn "OK"
else putStrLn "WRONG"
The idea is the same, the drawbacks too.
You could use parMap to apply the expensive function in parallel (if the dependencies permit) and a list of TVars corresponding to each list (or chunk of) element(s) and set them once the respective function application has completed. A separate thread could check on the values and update the display (obviously some IO action would happen here).
Related
With the following code:
(lazy_test.hs)
-- Testing lazy evaluation of monadically constructed lists, using State.
import Control.Monad.State
nMax = 5
foo :: Int -> State [Int] Bool
foo n = do
modify $ \st -> n : st
return (n `mod` 2 == 1)
main :: IO ()
main = do
let ress = for [0..nMax] $ \n -> runState (foo n) []
sts = map snd $ dropWhile (not . fst) ress
print $ head sts
for = flip map
I can set nMax to 5, or 50,000,000, and I get approximately the same run time:
nMax = 5:
$ stack ghc lazy_test.hs
[1 of 1] Compiling Main ( lazy_test.hs, lazy_test.o )
Linking lazy_test ...
$ time ./lazy_test
[1]
real 0m0.019s
user 0m0.002s
sys 0m0.006s
nMax = 50,000,000:
$ stack ghc lazy_test.hs
[1 of 1] Compiling Main ( lazy_test.hs, lazy_test.o )
Linking lazy_test ...
$ time ./lazy_test
[1]
real 0m0.020s
user 0m0.002s
sys 0m0.005s
which is as I expect, given my understanding of lazy evaluation mechanics.
However, if I switch from State to StateT:
(lazy_test2.hs)
-- Testing lazy evaluation of monadically constructed lists, using StateT.
import Control.Monad.State
nMax = 5
foo :: Int -> StateT [Int] IO Bool
foo n = do
modify $ \st -> n : st
return (n `mod` 2 == 1)
main :: IO ()
main = do
ress <- forM [0..nMax] $ \n -> runStateT (foo n) []
let sts = map snd $ dropWhile (not . fst) ress
print $ head sts
for = flip map
then I see an extreme difference between the respective run times:
nMax = 5:
$ stack ghc lazy_test2.hs
[1 of 1] Compiling Main ( lazy_test2.hs, lazy_test2.o )
Linking lazy_test2 ...
$ time ./lazy_test2
[1]
real 0m0.019s
user 0m0.002s
sys 0m0.004s
nMax = 50,000,000:
$ stack ghc lazy_test2.hs
[1 of 1] Compiling Main ( lazy_test2.hs, lazy_test2.o )
Linking lazy_test2 ...
$ time ./lazy_test2
[1]
real 0m29.758s
user 0m25.488s
sys 0m4.231s
And I'm assuming that's because I'm losing lazy evaluation of the monadically constructed list, when I switch to the StateT-based implementation.
Is that correct?
Can I recover lazy evaluation of a monadically constructed list, while keeping with the StateT-based implementation?
In your example, you're only running one foo action per runState, so your use of State and/or StateT is essentially irrelevant. You can replace the use of foo with the equivalent:
import Control.Monad
nMax = 50000000
main :: IO ()
main = do
ress <- forM [0..nMax] $ \n -> return (n `mod` 2 == 1, [n])
let sts = map snd $ dropWhile (not . fst) ress
print $ head sts
and it behaves the same way.
The issue is the strictness of the IO monad. If you ran this computation in the Identity monad instead:
import Control.Monad
import Data.Functor.Identity
nMax = 50000000
main :: IO ()
main = do
let ress = runIdentity $ forM [0..nMax] $ \n -> return (n `mod` 2 == 1, [n])
let sts = map snd $ dropWhile (not . fst) ress
print $ head sts
then it would run lazily.
If you want to run lazily in the IO monad, you need to do it explicitly with unsafeInterleaveIO, so the following would work:
import System.IO.Unsafe
import Control.Monad
nMax = 50000000
main :: IO ()
main = do
ress <- lazyForM [0..nMax] $ \n -> return (n `mod` 2 == 1, [n])
let sts = map snd $ dropWhile (not . fst) ress
print $ head sts
lazyForM :: [a] -> (a -> IO b) -> IO [b]
lazyForM (x:xs) f = do
y <- f x
ys <- unsafeInterleaveIO (lazyForM xs f)
return (y:ys)
lazyForM [] _ = return []
The other answer by K A Buhr explains why State vs StateT is not the pertinent factor (IO is), and also points out how your example is strangely constructed (in that the State(T) part isn't actually used as each number uses a new state []). But aside from those points, I'm not sure I would say "losing lazy evaluation of the monadically constructed list", because if we understand something like "lazy evaluation = evaluated only when needed", then foo does indeed need to run on every element on the input list in order to perform all the effects, so lazy evaluation is not being "lost". You are getting what you asked for. (It just so happens that foo doesn't perform any IO, and perhaps someone else can comment with if it's ever possible for a compiler/GHC to optimize it away on this basis, but you can easily see why GHC does the naive thing here.)
This is a common, well-known problem in Haskell. There are various libraries (best known of which are streaming, pipes, conduit) which solve the problem by giving you streams (basically lists) which are lazy in the effects too. If I recreate your example in a streaming style,
import Data.Function ((&))
import Control.Monad.State
import Streaming
import qualified Streaming.Prelude as S
foo :: Int -> StateT [Int] IO Bool
foo n =
(n `mod` 2 == 1) <$ modify (n:)
nMax :: Int
nMax = 5000000
main :: IO ()
main = do
mHead <- S.head_ $ S.each [0..nMax]
& S.mapM (flip runStateT [] . foo)
& S.dropWhile (not . fst)
print $ snd <$> mHead
then both versions run practically instantaneously. To make the difference more apparent, imagine that foo also called print "hi". Then the streaming version, being lazy in the effects, would print only twice, whereas your original versions would both print nMax times. As they're lazy in the effects, then the whole list doesn't need to be traversed in order to short-circuit and finish early.
I've read in multiple places that the writer monad of a list keeps that full list in memory, and therefore shouldn't be used in anything other than small samples (no logging, for instance).
For instance, read here
However, to test the claim, I wrote the following program, and actually showed that it successfully outputs an infinite list lazily!
import Control.Monad.Writer
createInfiniteList :: Int -> Writer [Int] ()
createInfiniteList i = do
tell [i]
createInfiniteList (i+1)
main :: IO ()
main = do
let x = execWriter $ createInfiniteList 1
print x
I've watched this program output over 1 billion items (it runs very fast), and monitored that the memory usage never went past 0.1% on my machine.
Has the writer monad been rewritten to fix the original problem? Can I count on it continuing to work this way in the future?
note- I am aware that better logging monads exist (I use those elsewhere)... My desired use case is not logging (but it is similar)
There are two factors at play here. The way the <>/mappend calls are nested, and whether the entire log is kept in memory.
How are the <> calls nested?
This depends on how you write your code using Writer, not on Writer's implementation. To see why, lets cheat.
data Tree a = Nil | Leaf a | Node (Tree a) (Tree a)
deriving (Show)
instance Semigroup (Tree a)
where x <> y = Node x y
instance Monoid (Tree a)
where mempty = Nil
This is not a proper monoid, since <> is not associative. x <> (y <> z) gives Node x (Node y z) whereas (x <> y) <> z) gives Node (Node x y) z. It allows us to tell after the fact whether the Writer's "log" was reduced left-nested or right nested.
go :: Int -> Writer (Tree Int) ()
go i
| i < 5
= do tell (Leaf i)
go (i+1)
| otherwise
= pure ()
main :: IO ()
main = do
let (result, log) = runWriter $ go 1
putStrLn (render log)
render Nil = "Nil"
render (Leaf x) = show x
render (Node x y) = "(" ++ render x ++ ") <> (" ++ render y ++ ")"
With this, you get: (1) <> ((2) <> ((3) <> ((4) <> (Nil))))
Clearly right-nested. Hence how you could generate an infinite list as the "log" of a Writer and consume it as it was generated in a relatively small amount of space.
But swap the order of the tell and the recursion, so that it looks like this:
go :: Int -> Writer (Tree Int) ()
go i
| i < 5
= do go (i+1)
tell (Leaf i)
| otherwise
= pure ()
And you get this: ((((Nil) <> (4)) <> (3)) <> (2)) <> (1). Now it's left-nested, infinite recursion does not work:
import Control.Monad.Writer
createInfiniteList :: Int -> Writer [Int] ()
createInfiniteList i = do
createInfiniteList (i+1)
tell [i]
main :: IO ()
main = do
let x = execWriter $ createInfiniteList 1
print x
This never prints anything, and consumes an ever-growing amount of memory.
Basically the structure of the <> calls is similar to the structure of your Writer expressions. Everywhere you bind in a call to another function (including the equivalent in a do-block), all of the <> calls resulting from that call will be "inside parentheses". So tell _ >> recurse results in right-nested <>s, while recurse >> tell _ results in left-nested <>s, and more complex call-graphs result in similarly-structured nesting of <>s.
Forcing the result builds the entire log
Another particular thing about your test program is that it doesn't use the "result" of the Writer at all, only the "log". Obviously if the recursion is infinite there's never any final result at all, but if we change your program like so:
import Control.Monad.Writer
createLargeList :: Int -> Writer [Int] ()
createLargeList i
| i < 50000000
= do tell [i]
createLargeList (i+1)
| otherwise
= pure ()
main :: IO ()
main = do
let (result, log) = runWriter $ createLargeList 1
print $ length log
print result
Then it behaves similarly; length consumes the list as it is produced and completes in short order (and relatively low memory usage). After that the () is readily available and is printed immediately.
But if we change it to print the result first:
import Control.Monad.Writer
createLargeList :: Int -> Writer [Int] ()
createLargeList i
| i < 50000000
= do tell [i]
createLargeList (i+1)
| otherwise
= pure ()
main :: IO ()
main = do
let (result, log) = runWriter $ createLargeList 1
print result
print $ length log
Then on my system this takes much longer, and consumes nearly 15 GB of RAM1. It does have to materialise the log fully in RAM just to get at the final result, even when the <>s are right-nested and the log can be consumed lazily.
Technically I believe it is not building the list in memory, but rather a chain of thunks applying <> to singleton lists, which is just as long as the final list and probably uses more memory per link in the chain. The resulting list is still consumed by length as it is generated by forcing those thunks, but that doesn't really help since the entire thunk chain had to be generated to get at the final () result, instead of having the thunk chain itself generates as length demands more of the list.
1 That's compiling like ghc foo.hs; if I compile with -O2 then it behaves similarly to printing the length of the log first. This is a fairly simple case for GHC to inline everything and figure out a better way of computing the same result; I wouldn't assume its optimisations could address this problem if the program were more complicated.
As part of my Haskell journey, I am implementing a raytracer and I need to be able to draw sequences of random numbers at several places in the code. Typically I would like to be able to get say 64 samples for each pixels and pixels are computed in parallel.
I was looking at the state monad to achieve that and I was guided by this answer Sampling sequences of random numbers in Haskell but the code I wrote does not terminate and it's memory consumption explodes.
Here is the abstracted part of the code:
I was hopping to be able to call sampleUniform several time in the code to get new lists of random numbers but if I do runhaskell test.hs, it outputs the first character of the lis [ and then it is stuck in an apparently infinite loop.
module Main (main
, computeArray) where
import Control.Monad
import Control.Monad.State (State, evalState, get, put)
import System.Random (StdGen, mkStdGen, random)
import Control.Applicative ((<$>))
type Rnd a = State StdGen a
runRandom :: Rnd a -> Int -> a
runRandom action seed = evalState action $ mkStdGen seed
rand :: Rnd Double
rand = do
gen <- get
let (r, gen') = random gen
put gen'
return r
{- Uniform distributions -}
uniform01 :: Rnd [Double]
uniform01 = mapM (\_ -> rand) $ repeat ()
{- Get n samples uniformly distributed between 0 and 1 -}
sampleUniform :: Int -> Rnd [Double]
sampleUniform n = liftM (take n) uniform01
computeArray :: Rnd [Bool]
computeArray = do
samples1 <- sampleUniform 10
samples2 <- sampleUniform 10
let dat = zip samples1 samples2
return $ uncurry (<) <$> dat
main :: IO ()
main = do
let seed = 48
let res = runRandom computeArray seed
putStrLn $ show res
uniform01 threads your state through an infinite number of computations, which means that although it produces its result lazily, there is no hope of retrieving a final state at the end to use for the next sampling. liftM (take n) only affects the final value, not the state effects used to compute it. Therefore as written, you can only use uniform01/sampleUniform once.
Instead you can thread the state through only as many rand actions as you use, e.g. with
sampleUniform n = mapM (\_ -> rand) $ replicate n ()
or simpler
sampleUniform n = sequence $ replicate n rand
I'm trying to create a simple counter which increases by 1 indefinitely, using IO.
I've been scratching my head ever since...
Ideally, I would like to do something along the lines of
tick = do putStr (counter)
counter + 1
where counter = 0
Then repeat the process. Then repeat the first 2 expressions. Or something along the lines of:
tick = tick'
where
counter = 1
tick' counter | counter > 0 = do putStrLn (show counter)
tick' (counter + 1)
| otherwise = tick
Which gives me errors :/
Any help is appreciated :)
There are a couple ways to do this without using a mutable cell. You already did it with your second attempt, there's just a little error. You need to pass an initial value to the tick' function, not "set it" (haskell does not have an idea of assigning variables -- only definitions. If the line x = y appears, x will be y for its entire lifetime).
tick = tick' 0
where ...
The counter = 0 line is not doing anything; it is defining a name that is never used. The counter used in the tick' function is bound as one of its arguments (and shadows the one defined to be 0). Take some time to stare at it with that in mind, see if that makes sense.
There is a nice "higher order" way we can do this too. Essentially we want to run the infinitely long block of code:
do
print 0
print 1
print 2
...
There is a function called sequence :: [IO a] -> IO [a] (see caveat below) that will take a list of actions and construct an action. So if we can construct the list [print 0, print 1, print 2, ...] then we can pass it to sequence to build the infinitely long block we are looking for.
Take note here, this is a very important concept in Haskell: [print 0, print 1, print 2] does not print those three numbers then construct the list [0,1,2]. Instead it is itself a list of actions, whose type is [IO ()]. Making the list does nothing; it is only when you bind an action to main that it will be executed. For example, we might say:
main = do
let xs = [putStrLn "hello", getLine >> putStrLn "world"]
xs !! 0
xs !! 0
xs !! 1
xs !! 1
xs !! 0
This would twice print hello, twice get a line and print world after each, then once print hello again.
With that concept, it is easy to build the list of actions [print 0, print 1, ...] with a list comprehension:
main = sequence [ print x | x <- [0..] ]
We can simplify a bit:
main = sequence (map (\x -> print x) [0..])
main = sequence (map print [0..])
So map print [0..] is the list of actions [print 0, print 1, ...] we were looking for, then we just pass that to sequence which chains them together.
This pattern of sequence is common, and has its own mapM:
mapM :: (a -> IO b) -> [a] -> IO [b]
mapM f xs = sequence (map f xs)
Thus:
main = mapM print [0..]
About as simple as you could want.
One note about performance: since we are not using the output of these functions, we should be using sequence_ and mapM_, with trailing underscores, which are optimized for that purpose. Usually this wouldn't matter in a Haskell program because of garbage collection, but in this particular use case is kind of a special case because of various subtleties. You'll find that without the _s, the memory usage of your program gradually grows as the list of results (in this case [(),(),(),...]) is constructed but never used.
Caveat: I have given the type signatures of sequence and mapM specialized to IO, not a general monad, so that the reader does not have to learn about the orthogonal concepts of actions having types and typeclasses at the same time.
Well, let's go back to basics. What you want appears to be an IO action that when bound, prints and increments a counter? I'm going to work from that assumption.
The first thing you need is some mutable cell, since you're using the same action each time. It needs to have something mutable inside it to do something different each time it's used. I'd go with an IORef for this case.
But keeping that IORef hidden is a bit tricky. Especially since globals are bad. The best way to do it is create the IO action from inside another IO action, and then close over the IORef. Doing so gives you something like this:
import Data.IORef
mkCounter :: IO (IO ())
mkCounter = do
ref <- newIORef 0
return $ do
counter <- readIORef ref
print counter
writeIORef ref $ counter + 1
This can be used by doing something like this:
main = do
tick <- mkCounter
tick
tick
tick
Your second implementation is really close!
tick = tick'
where
counter = 1
tick' counter | counter > 0 = do putStrLn (show counter)
tick' (counter + 1)
| otherwise = tick
Let's look at the errors for this:
Couldn't match expected type `IO b0' with actual type `a0 -> IO b0'
In the expression: tick'
Let's add some types to make sure we're getting what we want.
tick is an IO action. We don't care what value the action encapsulates, since the whole
point of it is to run forever.
tick :: IO a
Now our error is:
Couldn't match expected type `IO a' with actual type `a0 -> IO b0'
In the expression: tick'
Well, that's pretty much the same, no help there. Let's keep going.
tick' is a function that takes some integer and returns an IO action
that prints the integer and repeats tick' on the next value. Again, we don't care what
value the action encapsulates, since it runs forever.
tick' :: Int -> IO b
Wait, now that error makes sense! We defined tick = tick', but the two things have fundamentally different types. One is an action (tick) one is a function that returns an action (tick'). All we need to do is give tick' some value to get the action, so let's do that.
You'd tried to do that by saying where counter = 1 but all that did is define counter as 1 within the statement tick = tick', and since counter isn't mentioned there, it wasn't used.
When you said tick' counter | ... =, you weren't referring to the same counter as on the line above. There, you were defining another variable called counter that was only in scope within the definition of tick'.
So now our code looks like:
tick :: IO a
tick = tick' 1
where
tick' :: Int -> IO b
tick' counter | counter > 0 = do putStrLn (show counter)
tick' (counter + 1)
| otherwise = tick
If we try to compile it, ghc doesn't complain, and if we try it out in ghci it runs as desired:
% ghci
ghci> :l Tick.hs
Ok, modules loaded: Tick.
ghci> tick
1
2
3
...
25244
^C
Interrupted
ghci>
For a simple infinite counter just use recursion:
counter n = do print n
counter (n+1)
main = counter 1
Yet another way to implement tick functionality without using mutable state is to mix State and IO monad using monad transformers:
import Control.Monad.State
type Ticking a = StateT Int IO a
tick :: Ticking ()
tick = do
modify succ
get >>= liftIO . print
getCounterValue :: Ticking Int
getCounterValue = get
Then you can use it to create 'ticking' IO functions (with nuisance: IO functions here need to be prefixed with liftIO since it is now Ticking a monad not IO a):
ticking :: Ticking ()
ticking = do
liftIO $ putStrLn "Starting"
tick
tick
c <- getCounterValue
liftIO $ do
putStrLn ("Finished at " ++ show c)
putStrLn "Press any Enter to start infinite counter"
getChar
forever tick
Which can be converted into 'normal' IO using runStateT (with initial counter value):
startTicking :: Ticking a -> Int -> IO a
startTicking = evalStateT
So:
main :: IO ()
main = startTicking ticking 0
A forkIO safe version similar to Carl's answer using STM is
import Control.Concurrent.STM
import Control.Monad (replicateM_)
import Control.Monad(forever)
makeCounter :: IO (IO Int)
makeCounter = do
var <- newTVarIO 0
return $ do
atomically $ do
value <- readTVar var
modifyTVar var (+1)
readTVar var
-- a version that only counts from 1 to 10
main1:: IO ()
main1 = do
counter <- makeCounter
replicateM_ 10 $ counter >>= print
-- a version that counters forever
main2 :: IO ()
main2 = do
counter <- makeCounter
forever $ do
x<- counter
print x
main :: IO ()
main = do
counter <- makeCounter
tick<- counter
tick<- counter
print tick -- 2
Reference:
Mutable closures in Haskell and nested IO
An EXERCISE from STM tutorial
Mutable State in Haskell
As i understand Haskell does not have a global state, so is there any way to write a function f that will return f(n - 1) + 1, where n is a number of function call and f(1) = 0.
It should not accept any arguments and used like func f
Prelude> f ()
0
Prelude> f ()
1
Without using tricks like unsafePerform, it is not possible to define a function that can be called like you showed in your example. However it is possible to define an IO action that does what you want and could be used like this:
Prelude> x <- f
Prelude> x
0
Prelude> x <- f
Prelude> x
1
Here's an example program that does what you want using IORefs:
import Data.IORef
main = do counter <- newIORef 0
let f = do count <- readIORef counter
modifyIORef counter (+ 1)
return count
x <- f
print x
x <- f
print x
You're asking for a way to update some (possibly hidden) state on each call to a procedure, such that the function returns different results given the same input.
Clearly, that's no a referentially transparent function, so we must add something to Haskell's pure-by-default mode. We add notions of computation via monads. You just have to pick the monadic environment you need.
The state monad
The most precise way is to add just exactly the notion of state to your program, via the State monad (not to be confused with the "ST" monad):
import Control.Monad.State.Strict
-- a (stateful) procedure, that returns and increments an internal state counter
f :: State Int Int
f = do
n <- get
put (n+1)
return n
-- Call 'f' a bunch of times, print the final state.
main = print $ execState code 0
where
code = do f; f; f; f
Now 'f' has an internal state component.
Similarly, richer environments, such as IO, allow for State, so you could use the IO monad (or some other state-subsuming computational environment).
If you prefer something you can just type from the ghci command line then:
Prelude> :m + Data.IORef
Prelude Data.IORef> n <- newIORef 0
Prelude Data.IORef> let f = do { v <- readIORef n ; writeIORef n (v+1); return v}
Prelude Data.IORef> f
0
Prelude Data.IORef> f
1
Prelude Data.IORef> f
2
Prelude Data.IORef> f
3
Your example wanted to call "f ()", but that is a C-ism that Haskell does not have. If you really want that then just change the definition of "f" to start
let f _ = do {...
"()" is defined in Haskell as the unit value, which is the only value of the unit type "()". You can call "f" with any argument you want; it will be ignored.
Try something like this:
f 1 = 0
f n = f (n-1) + 1
EDIT: It seems I misunderstood your question; no, you cannot do something like that in haskell; functions ought to be pure. The function in your example is not pure