Self-Mutating `IO a` in Haskell - haskell

I would like to use IO Int to represent a stream of integers by hiding an IORef in its definition:
tickrate :: Int
tickrate = 20000
ioIntTest :: Int -> IO Int
ioIntTest i0 = do
intRef <- newIORef i0
f intRef
where
f :: IORef Int -> IO Int
f ref = do
i <- readIORef ref
modifyIORef ref (+1)
return i
ioTest :: Int -> IO ()
ioTest n = do
let intStream = ioIntTest n
intStreamToPrint intStream
where
intStreamToPrint is = do
threadDelay tickrate
c <- is
putStrLn (show c)
intStreamToPrint is
However, if I call ioTest n, rather than seeing an increasing list of numbers printed to the screen, I see only the starting number, n, repeating indefinitely.
While I could refactor this code so that incrementing and reading the value of ioIntTest i0 are done separately, I would like to know if/why the following is impossible:
Can I make an IO Int such that each time it is used in (>>=) (either explicitly or implicitly in do notation) the returned Int mutates?
While such an IO Int is perhaps not referentially transparent, I thought that was the point of wrapping computations in the IO monad.
Such a refactoring could be:
tickrate :: Int
tickrate = 20000
ioIntMutate :: IORef Int -> IO Int
ioIntMutate ref = do
i <- readIORef ref
modifyIORef ref (+1)
return i
ioTest :: Int -> IO ()
ioTest n = do
intStream <- newIORef n
intStreamToPrint intStream
where
intStreamToPrint is = do
threadDelay tickrate
c <- ioIntMutate is
putStrLn (show c)
intStreamToPrint is
In other words, is there any way to replace the line ioIntMutate is in the third-to-last line with an IO Int?

You can use IO (IO Int) for that. Like this:
ioIntTest :: Int -> IO (IO Int)
ioIntTest n = do
ref <- newIORef n
pure $ do
i <- readIORef ref
writeIORef ref (i+1)
pure i
ioTest :: Int -> IO ()
ioTest n = do
intStream <- ioIntTest n
intStreamToPrint intStream
where
intStreamToPrint is = do
threadDelay tickrate
c <- is
putStrLn (show c)
intStreamToPrint is
Note that the only difference between my ioTest and your ioTest is this line:
let intStream = ioIntTest n -- yours
intStream <- ioIntTest n -- mine
And, by the way, this solution is not so contrived. I have used a trick like this before to hide internal implementation details of an async RPC channel; or for another example on Hackage, check out once. You don't need to know whether that's implemented with IORefs or some other trick, and the author can switch tricks as they find better ones.
As a stylistic note, I'd write ioTest a little differently. One of these two:
ioTest :: Int -> IO ()
ioTest n = do
intStream <- ioIntTest n
forever (intStream >>= print >> threadDelay tickrate)
-- OR
forever $ do
intStream >>= print
threadDelay tickrate

Related

Haskell get values from IO domain

After reading the Haskell books I am kind of confused (or I simply forgot) how to get a value from the IO domain, into the 'Haskell world' to parse it, like so:
fGetSeq = do
input <- sequence [getLine, getLine, getLine]
fTest input
mapM_ print input
fTest = map (read :: String -> Int)
Obviously compiler complains. Couldn't match [] with IO. Is there a simple rule of thumb for passing values between 'worlds' or is it just my bad by omitting typesigs?
The thing about do notation is, every monadic action value in it (those to the right of <-s, or on their own line) must belong to the same monad. It's
do {
x <- ma ; -- ma :: m a x :: a
y <- mb ; -- mb :: m b y :: b ( with the same m! )
return (foo x y) -- foo x y :: c return (foo x y) :: m c
} -- :: m c
Now, since sequence [getLine, getLine, getLine] :: IO [String], this means your do block belongs in IO.
But you can treat the values in their own right, when you got them:
fGetSeq :: IO ()
fGetSeq = do
inputs <- sequence [getLine, getLine, getLine] -- inputs :: [String]
let vals = fTest inputs
mapM_ print vals
fTest :: [String] -> [Int]
fTest = map (read :: String -> Int)
-- or just
fGetSeq1 = do
inputs <- sequence [getLine, getLine, getLine]
mapM_ print ( fTest inputs )
-- or
fGetSeq2 = do { vals <- fTest <$> sequence [getLine, getLine, getLine] ;
mapM_ print vals } -- vals :: [Int]
-- or even (with redundant parens for clarity)
fGetSeq3 = mapM_ print =<< ( fTest <$> sequence [getLine, getLine, getLine] )
-- = mapM_ print . fTest =<< sequence [getLine, getLine, getLine]
The essence of Monad is the layering of the pure 'Haskell world' calculations in between the potentially impure, 'effectful' computations.
So we already are in the pure Haskell world, on the left hand side of that <-. Again, inputs :: [String]. A pure value.
get a value from the IO domain, into the 'Haskell world'
You use the bind operator: (>>=) :: Monad m => m a -> (a -> m b) -> m b.
If m = IO it looks like: (>>=) :: IO a -> (a -> IO b) -> IO b.
As you can see, the function with type a -> IO b addresses the a without IO.
So given a value in the IO monad, e.g. getLine :: IO String:
getInt :: IO Int
getInt = getLine >>= (\s -> return (read s))
Here, s :: String, read :: String -> Int, and return :: Int -> IO Int.
You can rewrite this using a do-block:
getInt :: IO Int
getInt = do
s <- getLine
return (read s)
Or use the standard library function that does exactly this:
getInt :: IO Int
getInt = readLn
As for your example, you can immediately fix it using a let-binding:
foo :: IO ()
foo = do
input <- sequence [getLine, getLine, getLine]
let ints = bar input
mapM_ print ints
bar :: [String] -> [Int]
bar = map read
Or you can restructure it to use getInt as defined above:
foo :: IO ()
foo = sequence [getInt, getInt, getInt] >>= mapM_ print

Factorial using imperative-style programming

I have the following code:
while :: IO Bool -> IO () -> IO ()
while test body =
do b <- test
if b
then do {body ; while test body} -- same-line syntax for do
else return ()
I need to implement the factorial function using imperative-style programming. what I have to do is to create and initialize variables using newIORef, modify their values using a while loop with readIORef and writeIORef, then have the IO action return a pair consisting of the input n and the final result.
This is what I have done so far:
fact :: Integer -> IO (Integer, Integer)
fact n = do r <- newIORef n --initialize variable
while
(do {v <- readIORef n; n})
(do {v <- readIORef r; writeIORef (...)) --modify the value (?)
readIORef r
This is my attempt to write the factorial function. This is obviously does not work. Any help would be appreciated.
I think maybe it's time to give you some working version:
fact :: Integer -> IO (Integer, Integer)
fact n = do
i <- newIORef 1
acc <- newIORef 1
while (lessOrEqualN i) (step i acc)
acc' <- readIORef acc
return $ (n, acc')
where
lessOrEqualN iRef = do
i' <- readIORef iRef
return $ i' <= n
step iRef accRef = do
i' <- readIORef iRef
acc' <- readIORef accRef
writeIORef accRef (acc' * i')
writeIORef iRef (i'+1)
as you can see I used an loop reference i and an accumulator reference acc always reading, writing the changing values.
To make this (hopefully) a bit more readable I extracted the test and the body of the while into lessOrEqualN and step.
Of course there are easier ways to do this (modifyIORef) but I guess you have to use those.
PS: you play with it a bit - maybe you want to handle negative values differently or whatever
this might be a bit cleaner (putting both mutables into the same ref):
fact :: Integer -> IO (Integer, Integer)
fact n = do
ref <- newIORef (1,1)
while (lessOrEqualN ref) (step ref)
(_,acc) <- readIORef ref
return $ (n, acc)
where
lessOrEqualN ref = do
(i,_) <- readIORef ref
return $ i <= n
step ref = do
(i,acc) <- readIORef ref
writeIORef ref (i+1, acc * i)
I think Carsten's answer can be made a bit cleaner like this:
{-# LANGUAGE TupleSections #-}
import Control.Monad
import Data.IORef
fact :: Integer -> IO (Integer, Integer)
fact n = do
counter <- newIORef 1
result <- newIORef 1
while (fmap (<=n) (readIORef counter)) $ do
i <- postIncrement counter
modifyIORef result (*i)
fmap (n,) (readIORef result)
while :: IO Bool -> IO () -> IO ()
while test body =
do b <- test
if b
then do {body ; while test body} -- same-line syntax for do
else return ()
postIncrement :: Enum a => IORef a -> IO a
postIncrement ref = do
result <- readIORef ref
modifyIORef ref succ
return result
What I'm doing here is:
Using modifyIORef to cut down on the number of paired readIORef/writeIORef calls.
Using fmap to reduce the need for auxiliary functions to test the contents of an IORef.
Write a generic, reusable postIncrement function and use that to shorten fact further.
But frankly, I think your instructor's insistence that you use this while function is a bit silly. It doesn't make for clean code. If I was told to write an imperative factorial with IORef I'd first write this, just using the forM_ loop from the library:
factorial :: Integer -> IO (Integer, Integer)
factorial n = do
result <- newIORef 1
forM_ [2..n] $ \i -> do
modifyIORef result (*i)
fmap (n,) (readIORef result)
And that's because I was too dumb to remember replicateM_ :: Monad m => Int -> m a -> m () right away...

getLine x times haskell

Based on Hackerrank question
My problem is how can I do getLine t times on stdIn?
main = do
t <- getInt
let x = [divisorsInNumber unsafeGetInt | a <-[1..t] ]
print x
getInt :: IO Int
getInt = fmap read getLine
unsafeGetInt :: Int
unsafeGetInt = unsafePerformIO getInt
divisorsInNumber n = length $ filter (== True) $ map (isDivisor n) (integralToListOfInts n)
Just replicate t times the getLine operation with replicateM:
import Control.Monad (replicateM)
getLines :: Int -> IO [String]
getLines t = replicateM t getLine
Thus getInts, that is getInt t times, can be expressed with:
getInts :: Int -> IO [Int]
getInts = fmap read <$> getLines
The full code rewritten to use getInts could be:
import Control.Applicative ((<$>))
import Control.Monad (replicateM)
getLines :: Int -> IO [String]
getLines n = replicateM n getLine
getInts :: Int -> IO [Int]
getInts n = fmap read <$> getLines n
getInt :: IO Int
getInt = fmap read getLine
divisorsInNumber :: Int -> Int
divisorsInNumber n = length $ filter (isDivisor n) (integralToListOfInts n)
main :: IO ()
main = do
t <- getInt
nums <- getInts t
let x = [divisorsInNumber num | num <- nums]
print x

Haskell STM : How to store ThreadID as per their execution sequence

In the following program Fibonacci number is generated from a given integer (generated randomly) and that value is stored into a TVar. As the execution time for generating the Fibonacci is different for different number, thus threads will not run sequentially. I want to store theadID, may be in a list, to check their execution pattern.
Please help me. Thanks in advance.
module Main
where
import Control.Parallel
import Control.Concurrent.STM
import Control.Concurrent
import System.Random
import Control.Monad
import Data.IORef
import System.IO
nfib :: Int -> Int
nfib n | n <= 2 = 1
| otherwise = par n1 (pseq n2 (n1 + n2 ))
where n1 = nfib (n-1)
n2 = nfib (n-2)
type TInt = TVar Int
updateNum :: TInt -> Int -> STM()
updateNum n v = do x1 <- readTVar n
let y = nfib v
x2 <- readTVar n
if x1 == x2
then writeTVar n y
else retry
updateTransaction :: TInt -> Int -> IO ()
updateTransaction n v = do atomically $ updateNum n v
incR :: IORef Int -> Int -> IO ()
incR r x = do { v <- readIORef r;
writeIORef r (v - x) }
main :: IO ()
main = do
n <- newTVarIO 10
r <- newIORef 40;
forM_ [1..10] (\i -> do
incR r i
;v <- readIORef r
;forkIO (updateTransaction n v)
)
I want to store [TreadID,FibNo] into a List for all the threads as per their execution. Suppose T1 has executed Fib30, T2 Fib35, T3->32 and T4->40. And if the commit sequence of threads like T1,T3, T2 and T4 then I want to store T1-35,T3-32,t2-35,t4-40 in a list.
Edit:
As suggested by #MathematicalOrchid, I have modified updateTrasaction as follows:-
updateTransaction :: MVar [(ThreadId, Int)] -> TInt -> Int -> IO ()
updateTransaction mvar n v = do
tid <- myThreadId
atomically $ updateNum n v
list <- takeMVar mvar
putMVar mvar $ list ++ [(tid, v)]
Now I am trying to print the values from that list in main
main :: IO ()
main = do
...
...
m <- newEmptyMVar
...
...
mv <- readMVar m
putStrLn ("ThreadId, FibVal : " ++ " = " ++ (show mv))
At the time of execution. MVar values couldn't be read and generates error
Exception: thread blocked indefinitely in an MVar operation
What to do? Thank in advance.
Did you want something like
updateTransaction :: TInt -> Int -> IO ()
updateTransaction n v = do
tid <- myThreadId
putStrLn $ "Start " ++ show tid
atomically $ updateNum n v
putStrLn $ "End " ++ show tid
Or perhaps something like
updateTransaction :: TInt -> Int -> IO ThreadId
updateTransaction n v = do
atomically $ updateNum n v
myThreadId
and change forM_ to forM?
Also, this part:
do
x1 <- readTVar n
...
x2 <- readTVar n
if x1 == x2 ...
If x1 /= x2 then GHC will automatically abort and restart your transaction. You do not need to manually check this yourself. Indeed, the else-branch can never execute. That's kind of the point of STM; it will appear to your transaction that nobody else changes the data you're looking at, so you don't ever have to worry about concurrent writes.
Edit: If you want to record the actual order in which the transactions committed, you're going to need some more inter-thread communication. Obviously you could do that with STM, but just for a list of stuff, maybe this could work?
updateTransaction :: MVar [(ThreadId, Int)] -> TInt -> Int -> IO ()
updateTransaction mvar n v = do
tid <- myThreadId
fib <- atomically $ updateNum n v
list <- takeMVar mvar
putMVar mvar $ list ++ [(tid, fib)]
(Obviously you have to make updateNum return the number it calculated.)

Haskell type error with forkFinally I just can't work out

Along with the error I'm having, any tips on how terrible what I'm doing is would be appreciated.
So I'll paste the code, it's a bit; but I think it's mostly correct, I just can't get forkFinally to type check...
The error is on the only line that calls forkFinally:
Ambiguous type variable `e0' in the constraint:
(Exception e0) arising from a use of `forkFinally'
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of a 'do' block:
t <- forkFinally (echoHandler a) (exitPool p)
In the expression:
do { a <- accept s;
t <- forkFinally (echoHandler a) (exitPool p);
atomically
$ do { p' <- readTVar p;
writeTVar p (t : p') };
repeatAccept s p }
In an equation for `repeatAccept':
repeatAccept s p
= do { a <- accept s;
t <- forkFinally (echoHandler a) (exitPool p);
atomically
$ do { p' <- readTVar p;
.... };
.... } Failed, modules loaded: none.
Here's the code:
type ConnectionHandler = (Handle, HostName, PortNumber) -> IO ()
type Pool = TVar [ThreadId]
runConn = do
s <- withSocketsDo (listenOn (PortNumber 1234))
p <- atomically (newTVar ([]::[ThreadId]))
t <- forkIO (repeatAccept s p)
repeatUntilExit stdin stdout putChar ""
p' <- atomically (readTVar p)
mapM killThread (t:p')
repeatAccept s p = do
a <- accept s
t <- forkFinally (echoHandler a) (exitPool p) -- Error here, forkIO instead compiles fine.. (and I guess actually should work just fine too?)
atomically $ do
p' <- readTVar p
writeTVar p (t:p')
repeatAccept s p
exitPool :: Pool -> a -> IO ()
exitPool pool = \_ -> do
tid <- myThreadId
atomically $ do
pool' <- readTVar pool
writeTVar pool $ filter (/=tid) pool'
return ()
echoHandler :: ConnectionHandler
echoHandler a#(hdl,_,_) = repeatUntilExit hdl hdl echoToHandleAndStdout ""
where echoToHandleAndStdout x = hPutChar hdl x >> putChar x
repeatUntilExit :: Handle -> Handle -> (Char -> IO ()) -> [Char] -> IO ()
repeatUntilExit hIn hOut f "exit\n" = hPutStrLn hOut "bye\n"
repeatUntilExit hIn hOut f x = hGetChar hIn >>= \c -> f c >> repeatUntilExit hIn hOut f (appendToLastFive c)
where appendToLastFive a = (reverse . (:)a . take 4 . reverse) x
forkFinally :: Exception e => IO a -> (Either e a -> IO ()) -> IO ThreadId
forkFinally action and_then =
mask $ \restore ->
forkIO $ try (restore action) >>= and_then
Type signature for forkFinally in the latest Control.Concurrent:
forkFinally :: IO a -> (Either SomeException a -> IO ()) -> IO ThreadId
Type signature for forkFinally in your code:
forkFinally :: Exception e => IO a -> (Either e a -> IO ()) -> IO ThreadId
You have tried to generalise the exception type. This isn't a problem if the exception type can be deduced from forkFinally's second parameter. But this is forkFinally's second parameter:
exitPool p :: a' -> IO ()
The type checker tries to unify Either e a -> IO () with a' -> IO () and ends up not being able to deduce what e is.
General solution: specify an explicit type. e.g.
t <- forkFinally (echoHandler a) (exitPool p :: Either SomeException () -> IO ())
Better specific solution: restore the original type signature to forkFinally. It doesn't seem to make sense for it to only catch a limited set of exceptions.

Resources