It depends your allocation pattern. If you only need to allocate a single handle, then you can factor out the `withFile` outside of `runWorkers` and pass the handle to `runWorkers`:

    withFile "yourFile.txt" ReadMode $ \handle -> do
        runWorkers handle ...
        ...

Then you use `fromHandle` within `runWorkers` to read from that handle.

If you need to allocate the handle within `runWorkers` for any reason, then there are two alternatives.

A) First, `pipes-safe` doesn't support `MonadBaseControl` (because its semantics are not well specified), so if you went that route you would need to use the non-lifted `async` and do something like this:

    ...
    inp <- async $ do
        withFile someFile ReadMode $ \handle ->
            runEffect $ fromHandle h >-> ...
    ...

B) Implement `withFile` in terms of `resourcet`, which does support `MonadBaseControl`. In fact, I may replace `pipes-safe` with `resourcet` since they are very similar to each other, with the main difference being that I try to avoid `MonadBaseControl`. If you go this route, then just use the `withFile` function from the following lpaste:

http://lpaste.net/101607

Then you can use that within your lifted `async` like this:

    ...
    inp <- async $ do
        withFile someFile ReadMode $ \producer  ->
            runEffect $ producer >-> ...
    ...

Let me know which solution works best for you. Right now I'm studying whether or not to outsource `pipes-safe` to `resourcet` and your feedback on this would be welcome.

On 03/18/2014 05:05 PM, Lieven Marchand wrote:
Hi,

I wrote a little routine to run a bunch of computations in parallel using pipes like this

type Generator a b m = (Monad m) => a -> Producer b m ()
type Worker b c m = (Monad m) => Pipe b c m ()
type Sync c m = (Monad m) => Consumer c m ()

runWorkers n a g w s = do
    (output, input) <- liftIO $ spawn Unbounded
    (output', input') <- liftIO $ spawn Unbounded
    inp <- async $ do
        runEffect $ (g a) >-> toOutput output
        liftIO performGC
    out <- async $ do
        runEffect $ fromInput input' >-> s
        liftIO performGC
    workers <- forM [1..n] $ \_ ->
        async $ do
            runEffect $ fromInput input >-> w >-> toOutput output'
            liftIO performGC
    mapM_ wait (inp:out:workers)

and now I want to use Pipes.Safe.Prelude's withFile in one of my generators.

But when I tried to do

PSP.runSafeT $ runWorkers

I get the error
    No instance for (MonadBaseControl IO (PS.SafeT IO))
      arising from a use of `runWorkers'
    Possible fix:
      add an instance declaration for (MonadBaseControl IO (PS.SafeT IO))

and trying to fix this led me into a whole bunch of other problems.

What is the preferred way to do this kind of thing?

Thanks.

--
You received this message because you are subscribed to the Google Groups "Haskell Pipes" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected] <mailto:[email protected]>. To post to this group, send email to [email protected] <mailto:[email protected]>.

--
You received this message because you are subscribed to the Google Groups "Haskell 
Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].

Reply via email to