我想收到一个字符串,将其转换为列表并将列表的每个元素写入TChan。对于收到的每个字符串,我想分叉一个新进程。
我的问题是,当我尝试编译时,我得到与IO相关的错误:
Couldn't match expected type `IO ()' with actual type `[()]'
或
Couldn't match expected type `IO ()' with actual type `[IO ()]'
虽然我完全理解错误并知道它的起源(至少是第一个错误 - )但我现在已经不知道如何在我的示例中拆分IO计算并仍然实现我尝试做的事情。 / p>
write2TChan msg mtch = do
let mymessages = words msg
map (\x -> atomically $ writeTChan mtch x) mymessages
return ()
main = withSocketsDo $ do
s <- socket AF_INET Datagram defaultProtocol
bindAddr <- inet_addr host
bindSocket s (SockAddrInet port bindAddr)
mtch <- newTChanIO
let forever socket hosts = do
(msg, host) <- receiveMessage socket
return ()
return (forkIO $ write2TChan msg mtch)
--forkIO $ write2TChan msg mtch
--tried w return () and above, same problem
forever socket hosts
forever s []
sClose s
答案 0 :(得分:6)
map
的类型为map :: (a -> b) -> [a] -> [b]
,因此它始终返回列表。但是,do
monad中IO
块中的每个语句都必须为某些IO a
添加a
类型。
您希望相关函数mapM :: Monad m => (a -> m b) -> [a] -> m [b]
在monad中执行相同的操作。由于您要忽略结果,我们可以使用变体mapM_ :: Monad m => (a -> m b) -> [a] -> m ()
。
write2TChan msg mtch = do
let mymessages = words msg
mapM_ (\x -> atomically $ writeTChan mtch x) mymessages
对于您的其他功能,您应该可以直接使用forkIO
。将其包含在return
中完全没有任何意义,因为它会生成类型IO (IO a)
,即返回操作的操作。此外,当return ()
不是do
块中的最后一个语句时,let forever socket hosts = do
(msg, host) <- receiveMessage socket
forkIO $ write2TChan msg mtch
forever socket hosts
是无操作,因此您不需要它。
这应该有效
hosts
但是,[]
参数目前总是forever
,所以除非你打算对此做些什么,否则你也可以摆脱它。另外,我会避免使用名称Control.Monad
,因为{{1}}中已经有一个常用的具有该名称的函数。