使用Control.Concurrent.MonadIO

时间:2017-09-08 21:57:19

标签: haskell monad-transformers haskell-pipes

在下面的代码中,我尝试将2 Producer组合成1.所有类型都相同。它们将由在一个单独的线程中运行的2个输入Producer中的每一个组合,并由Consumer使用,它将值放入unagi chan(我使用unagi chan为性能)。返回一个从chan读取的生产者。我希望能够使用任何Producer,只要它可以IO运行,因此我将monad的类限制为MonadIOHasFork

import Pipes (Producer, Consumer, (>->), yield, await, runEffect)
import Control.Concurrent.Chan.Unagi (InChan, OutChan, newChan, readChan, writeChan)
import Control.Monad (forever, void)
import Control.Concurrent.MonadIO (MonadIO, HasFork, liftIO, fork)

combine :: (MonadIO m, HasFork m) => Producer a m r -> Producer a m r -> Producer a m r
combine p1 p2 = do
  (inChan, outChan) <- liftIO $ newChan
  t1 <- fork . void . runEffect $ p1 >-> (consumer inChan)
  t2 <- fork . void . runEffect $ p2 >-> (consumer inChan)
  producer outChan

producer :: (MonadIO m) => OutChan a -> Producer a m r
producer outChan = forever $ do
  msg <- liftIO $ readChan outChan
  yield msg

consumer :: (MonadIO m) => InChan a -> Consumer a m r
consumer inChan = forever $ do
  msg <- await
  liftIO $ writeChan inChan msg

但是我收到以下错误:

    • Couldn't match type ‘m’
                 with ‘Pipes.Internal.Proxy Pipes.Internal.X () () a m’
  ‘m’ is a rigid type variable bound by
    the type signature for:
      combine :: forall (m :: * -> *) a r.
                 (MonadIO m, HasFork m) =>
                 Producer a m r -> Producer a m r -> Producer a m r
    at src/Pipes/Unagi.hs:8:12
  Expected type: Pipes.Internal.Proxy
                   Pipes.Internal.X () () a m GHC.Conc.Sync.ThreadId
    Actual type: m GHC.Conc.Sync.ThreadId

我正在尝试做什么?

1 个答案:

答案 0 :(得分:2)

lift前面添加fork

t1 <- lift . fork . ...

在您的函数中,fork . ...的类型为m ThreadId,但do块位于monad Producer a m中。

此外,lifted-base还有更新的fork