How to sleep or delay the thread in Haskell? - haskell

This really shouldn't be so difficult to find an answer to, but alas I don't... I want to delay the next execution step in a do block. I have found the functions
delay,
sleep,
nanosleep and
usleep.
And also this question, that doesn't cover how to use any of these, however: Sleep in Haskell.
I am getting the same error for all of these, so probably I am doing something wrong fundamentally:
Variable not in scope: delay :: Integer -> IO a0
This is my test snippet:
main = do
{
putStrLn "line 1"
; delay 2
; putStrLn "line 2"
}
Googling the error does not actually yield anything useful for some reason.

Well, you have to import Control.Concurrent first:
import Control.Concurrent
threadDelay 1000000 --sleep for a million microseconds, or one second

Related

Growing stack size w/ inadvertent loop statement - expected behavior?

First the Question - is the behavior below expected logically, or a bug to be reported for GHC?
The code below will leak memory (tested on ghc-8.8.4) because ghc seems to add join point and jumps to it at the end of the loop, building up the stack.
{-# OPTIONS_GHC -fno-full-laziness #-}
module Main where
import Control.Concurrent.Async (async,waitCatch)
import Data.IORef
import GHC.Conc
main :: IO ()
main = do
val <- newIORef 0 :: IO (IORef Int)
let loop1 = do
cval <- readIORef val
threadDelay 1
writeIORef val (cval + 1)
case cval > 100000000 of
True -> error "done"
False -> loop1
loop1 -- Deliberately, add this to cause space leak, but this statement is never executed because of case branching above
loop1Async <- async loop1
res <- waitCatch loop1Async
return ()
Compiling with -O2 -rtsopts -threaded and running with +RTS -s -hT -N will show space leak because of growing stack.
Looking at core output, it seems the leak is due to join (I guess it is a join point) and a jump to it at the end of the loop which grows the stack (if I have read the core correctly). Removing the last statement in loop1 fixes the leak.
ghc core output is here.
Update: Based on feedback in comments, it seems to be logical behavior, not a bug in ghc. So, an answer explaining stack increase would be good to have. This helps us understand what is going on here. ghc core output has been posted above.
I would certainly expect that line to cause the use of stack space. That extra call to loop1 is hardly irrelevant.
Change the test constant to 10 instead of a larger number, and replace the return () branch with print cval.
Compare the output you get with and without the "never executed" statement. You might find it's somewhat more executed than you think.

Why this two function created by forkIO in haskell can't be run one by one?

I have this prog in windows ghc:
import Control.Concurrent
a=print 1
b=print 2
main=do
forkIO a
forkIO b
it can only print 1 in console,Why?
I think the main thread run first,then it create a thread,run function a,print 1,then create another thread,run function b,then print 2
so the console will give me
1
2
Ok, I think I remember something about "a Haskell program ends when the main thread exits". So the main thread is ending before the other threads have had a chance to do their thing. A quick fix is
main = do
forkIO a
forkIO b
threadDelay (10^6) -- 1 second
A less quick, more correct fix is to use MVars to simulate "joining" a thread -- i.e. waiting until it completes.

typed-process withProcessWait_ and getExitCode race condition?

import System.Process.Typed
import Control.Monad.STM
import Control.Concurrent.STM.TVar
processConf = setStderr byteStringOutput . setStdout byteStringOutput
main :: IO ()
main = do
withProcessWait_ (processConf $ proc "sleep" ["1"])
$ \p -> do
atomically (getStdout p) >>= print
atomically (getStderr p) >>= print
getExitCode p >>= print
print "test"
The above code mostly returns Nothing for the exit code, while other times it'll return Just ExitSuccess, so seemingly random / race condition.
Why might this occur?
The function in question is: http://hackage.haskell.org/package/typed-process-0.2.6.0/docs/System-Process-Typed.html#v:withProcessWait_
withProcessWait_ :: MonadUnliftIO m => ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> m a) -> m a
My understanding of what the function will do is, run the process, wait till it's terminated and then run the IO a. However... I just noticed there is a readProcess function which sounds like what I should actually be using instead http://hackage.haskell.org/package/typed-process-0.2.6.0/docs/System-Process-Typed.html#v:readProcess
None the less, it would be useful to know what is actually happening in the above / withProcessWait_.
The race condition is that three separate threads are consuming all available standard output (first thread) and standard error (second thread) and waiting on the exit code (third thread). The standard output and standard error thread can complete and publish the full output to STM before the third thread publishes the exit code.
Since getExitCode checks the exit code TMVar but doesn't wait on it, the exit code may not be available. (In fact, if the child process closes standard output and error before exiting, it may genuinely still be running at this point!)
If you replace getExitCode with waitExitCode, you reliably get ExitSuccess. Of course, withProcessWait_ is already waiting on the exit code and will raise an exception if it's not ExitSuccess, so there's no particular reason to do this anyway.

Is there a way in Haskell to check if a minute has passed since the previous current time?

I'm new to Haskell and I'm trying to set up a bot that gives you points according if a minute has passed
I've tried looking up ways to get a current time and adding a minute on top of that and check whenever that would equal when a minute has passed such as addUTCTime.
How I would love it to look is just like this
if(timeNow == timeInAMinute) then sendMsg ("You got a point added!") else return ()
I've come to no avail just yet, so I would hope there is some actual way to go about this. I also still have to deal with the IO stuff still. So back to my question, is there a way to check if a minute has passed from the current time?
This would do basically what you're asking:
import Data.Time
main :: IO ()
main = do
t0 <- getCurrentTime
go t0
where go tl = do
t <- getCurrentTime
if t >= 60`addUTCTime`tl
then do
putStrLn "You got a point!"
go t
else go tl
Of course, this busy waiting in a recursive loop isn't exactly efficient. A much simpler and better solution would be just
import Control.Concurrent (threadDelay)
import Control.Monad (forever)
main :: IO ()
main = forever $ do
threadDelay $ 60 * 10^6
putStrLn "You got a point!"

My timer always returns 0

I have created a timer in haskell. The problem is, it always returns 0. I think this is because of laziness, but I do not know how to fix it.
import System.CPUTime
timeit::IO ()->IO (Float)
timeit io=do
start <-getCPUTime
action <-seq start io
end <-seq action getCPUTime
return $! (fromIntegral $ end-start)/(10**12)
As you can see, I have throw in seq and $! galor, but to no avail. What do I do?
Here in an example run:
*Main> timeit test
What is your name?
Haskell
Your name is Haskell.
0.0
Here is some code I got to work
import Data.Time.Clock
timeit::IO ()->IO NominalDiffTime
timeit doit=do
start <- getCurrentTime
doit
end <- getCurrentTime
return (diffUTCTime end start)
Now for some discussion-
From the comments it seemed that you wanted real time, not cpu time, so that is what I wrote.
The System.Time libary is deprecated, so I switched you to the Data.Time library.
NominalDiffTime holds the time in seconds....
NominalDiffTime ignores leap seconds! In the unlikely event that a leap second is added during the running of the program, a 10 second delay will show up as 11 seconds. I googled around on how to fix this, and although Data.Time does have a DiffTime type to account for this, there doesn't seem to be a simple way to generate a DiffTime from UTCTime. I think you may be able to use the Posix time libraries and get seconds from Jan 1, 1970.... Then take the diff, but this seems like to much hastle for a pretty rare bug. If you are writing software to safely land airplanes however, please dig a bit deeper and fix this problem. :)
I've used this before and it works well for approximations. Don't rely on it for very precise times, but it should be accurate to within a millisecond. I've never tested its accuracy, so use at your own risk
import System.CPUTime
timeit :: IO a -> IO (a, Integer)
timeit action = do
start <- getCPUTime
value <- action
end <- getCPUTime
return (value, end - start)
No explicit strictness required.

Resources