Jim*_*ffa 0 multithreading haskell network-programming
随着我所遇到的错误,任何关于我正在做多么可怕的提示都将不胜感激.
所以我会粘贴代码,它有点; 但我觉得这大多是正确的,我只是不能得到forkFinally来打字检查......
错误发生在调用forkFinally的唯一行上:
Run Code Online (Sandbox Code Playgroud)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.
这是代码:
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
Run Code Online (Sandbox Code Playgroud)
forkFinally在最新的Control.Concurrent中键入签名:
forkFinally :: IO a -> (Either SomeException a -> IO ()) -> IO ThreadId
Run Code Online (Sandbox Code Playgroud)
forkFinally在代码中键入签名:
forkFinally :: Exception e => IO a -> (Either e a -> IO ()) -> IO ThreadId
Run Code Online (Sandbox Code Playgroud)
您试图概括异常类型.如果可以从forkFinally第二个参数推导出异常类型,则这不是问题.但这是forkFinally第二个参数:
exitPool p :: a' -> IO ()
Run Code Online (Sandbox Code Playgroud)
该类型检查试图统一Either e a -> IO ()与a' -> IO ()和最终不能够推断出e的.
一般解决方案:指定显式类型.例如
t <- forkFinally (echoHandler a) (exitPool p :: Either SomeException () -> IO ())
Run Code Online (Sandbox Code Playgroud)
更具体的解决方案:将原始类型签名恢复为forkFinally.仅仅捕获一组有限的异常似乎没有意义.
| 归档时间: |
|
| 查看次数: |
150 次 |
| 最近记录: |