2016-08-30 2 views
1

Я разрабатываю приложение Yesod, и я сталкиваюсь с ошибкой при попытке использовать sendFlush и sendChunkBS внутри forkIO.Использование sendFlush и sendChunkBS в forkIO

sendFlush и sendChunkBS имеют тип Monad m => Producer m (Flush Builder) но forkIO требует IO().

Вот код:

respondSource "" $ do 
    sendFlush 

    (rid, rwait) <- liftIO $ T.forkIO $ 
    do 
     let loop = do 
      output <- liftIO $ SB.recv targetSocket (2^11) 
      liftIO $ putStrLn $ "SB.recv: " ++ BSC.unpack output 

      when (not $ BS.null output) $ 
       do 
       sendChunkBS output 
       sendFlush 
       loop 
     loop 

и ошибка:

Couldn't match expected type ‘IO a0’ 
      with actual type ‘C.ConduitM 
           i0 (C.Flush Data.ByteString.Builder.Internal.Builder) m0()’ 
Relevant bindings include 
    loop :: C.ConduitM 
      i0 (C.Flush Data.ByteString.Builder.Internal.Builder) m0() 
    (bound at app/Main.hs:96:13) 
In a stmt of a 'do' block: loop 
In the second argument of ‘($)’, namely 
    ‘do { let loop = ...; 
     loop }’ 

ответ

1

Я хотел бы попробовать добавить вызов runConduit непосредственно перед forkIO;

(rid, rwait) <- liftIO $ T.forkIO $ runConduit $ 

Ваш аргумент forkIO является ConduitM действие, и runConduit преобразует что действие ввода-вывода.

+0

'runConduit' не работает, потому что для этого требуется' ConduitM', содержащая 'Data.Void.Void', но вместо этого у меня есть' ConduitFlush'. –

0

Стандартным подходом к этому было бы создание какой-либо общей переменной для связи между дочерним потоком и основным потоком, а также сбрасывать значения основного потока из переменной и send с соответствующими функциями. Моя рекомендация заключалась бы в использовании Software Transactional Memory (STM) и, вероятно, что-то вроде TBQueue.