Haskell 如何安全地中止getChar?
我想选择性地中止Haskell 如何安全地中止getChar?,haskell,io,Haskell,Io,我想选择性地中止getChar操作。 我需要以下功能: getChar' :: (Char -> IO ()) -> IO (IO ()) 如果是中止IO())->IO(IO()) getChar'callback=do v您要做的是使用异常处理结构,这样无论出现什么异常,MVar都始终处于安全状态。特别是,您可能需要使用MVAR我认为实现这一点的最简单方法是执行您自己的缓冲。这是一个简单的原型。它假定您在程序中只调用一次launchIOThread。它不处理EOF或其他IO异常,
getChar
操作。
我需要以下功能:
getChar' :: (Char -> IO ()) -> IO (IO ())
如果是中止IO())->IO(IO())
getChar'callback=do
v您要做的是使用异常处理结构,这样无论出现什么异常,MVar都始终处于安全状态。特别是,您可能需要使用MVAR
我认为实现这一点的最简单方法是执行您自己的缓冲。这是一个简单的原型。它假定您在程序中只调用一次launchIOThread
。它不处理EOF或其他IO异常,但这应该很容易
import Control.Concurrent
import Control.Concurrent.STM
import Data.Maybe
import Control.Monad
type Buffer = TVar (Maybe Char)
launchIOThread :: IO Buffer
launchIOThread = do
buf <- atomically $ newTVar Nothing
_ <- forkIO $ ioThread buf
return buf
ioThread :: Buffer -> IO ()
ioThread buf = loop where
loop =
join $ atomically $ do
contents <- readTVar buf
if isJust contents -- no-one has taken the character yet
then retry -- relax
else return $ do
c <- getChar
atomically $ writeTVar buf (Just c)
loop
getChar' :: Buffer -> (Char -> IO ()) -> IO (IO ())
getChar' buf callback = do
abortFlag <- atomically $ newTVar False
_ <- forkIO $ doGetChar abortFlag
return $ atomically $ writeTVar abortFlag True
where
doGetChar abortFlag = join $ atomically $ do
mbC <- readTVar buf
abort <- readTVar abortFlag
case mbC of
Just c ->
do writeTVar buf Nothing; return $ callback c
Nothing | abort -> return $ return ()
_ -> retry
导入控制。并发
导入控制.Concurrent.STM
导入数据,也许吧
进口管制
类型Buffer=TVar(可能是Char)
launchIOThread::IO缓冲区
launchIOThread=do
buf即使我们假设getChar
没有引发异常,问题仍然存在,因此with mvar
没有帮助。谢谢!STM和全局缓冲区在这里不可避免吗?您认为,getChar
也可以在IO
中定义,而不影响其语义吗?编辑:我想是的,因为IO
可能有全局状态。我想知道为什么getChar':(Char->IO())->IO(IO())
不在Prelude
或System.IO
中,它有简单的语义,而且似乎无法用现有的构造进行定义(我的意思是没有缓冲区
参数)。是的,Haskell.2中有创建全局变量的方法。前奏曲是一个模块,就像其他模块一样。把它放在序曲中并不能使它变得神奇。也许您的意思是为什么GHC自己的IO系统不提供此功能。我想,没有人会费心去做。。。
import Control.Concurrent
import Control.Concurrent.STM
import Data.Maybe
import Control.Monad
type Buffer = TVar (Maybe Char)
launchIOThread :: IO Buffer
launchIOThread = do
buf <- atomically $ newTVar Nothing
_ <- forkIO $ ioThread buf
return buf
ioThread :: Buffer -> IO ()
ioThread buf = loop where
loop =
join $ atomically $ do
contents <- readTVar buf
if isJust contents -- no-one has taken the character yet
then retry -- relax
else return $ do
c <- getChar
atomically $ writeTVar buf (Just c)
loop
getChar' :: Buffer -> (Char -> IO ()) -> IO (IO ())
getChar' buf callback = do
abortFlag <- atomically $ newTVar False
_ <- forkIO $ doGetChar abortFlag
return $ atomically $ writeTVar abortFlag True
where
doGetChar abortFlag = join $ atomically $ do
mbC <- readTVar buf
abort <- readTVar abortFlag
case mbC of
Just c ->
do writeTVar buf Nothing; return $ callback c
Nothing | abort -> return $ return ()
_ -> retry