Skip to content

Instantly share code, notes, and snippets.

@tallpeak
Last active October 23, 2018 21:50
Show Gist options
  • Save tallpeak/f198719a3dec264500e54a6a137b34b6 to your computer and use it in GitHub Desktop.
Save tallpeak/f198719a3dec264500e54a6a137b34b6 to your computer and use it in GitHub Desktop.
-- https://stackoverflow.com/questions/4522387/how-can-i-emulate-gos-channels-with-haskell/38277207#38277207
import Control.Monad
import Control.Concurrent (forkIO, ThreadId, threadDelay)
import Control.Concurrent.Chan (newChan, readChan, writeChan, Chan)
import Control.Concurrent.MVar (newMVar, swapMVar, readMVar, MVar)
data GoChan a = GoChan { chan :: Chan a, closed :: MVar Bool }
go :: IO () -> IO ThreadId
go = forkIO
make :: IO (GoChan a)
make = do
ch <- newChan
cl <- newMVar False
return $ GoChan ch cl
get :: GoChan a -> IO a
get ch = do
cl <- readMVar $ closed ch
if cl
then error "Can't read from closed channel!"
else readChan $ chan ch
(=->) :: a -> GoChan a -> IO ()
v =-> ch = do
cl <- readMVar $ closed ch
if cl
then error "Can't write to closed channel!"
else writeChan (chan ch) v
--forRange :: GoChan a -> (a -> IO b) -> IO [b]
forRange ch func =
range_ ch func []
where range_ ch func acc = do
cl <- readMVar $ closed ch
if cl
then return $ reverse acc
else do
v <- get ch
func v
range_ ch func $ v : acc
close :: GoChan a -> IO ()
close ch = do
swapMVar (closed ch) True
return ()
generate :: GoChan Int -> IO ()
generate c = do
forM [1..9999] (=-> c)
threadDelay 33
close c
--process :: GoChan Int -> IO ()
process c = forRange c print
main :: IO ()
main = do
c <- make
go $ generate c
process c
return ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment