Having a producer of type Producer ByteString IO () and a pipe of type Pipe ByteString a IO () how do I compose an effect, which will result in IO a when run?
Here's my best attempt:
{-# LANGUAGE ScopedTypeVariables #-}
import Pipes
import Data.ByteString
run :: forall a. IO a
run = runEffect $
(undefined :: Producer ByteString IO ()) >-> (undefined :: Pipe ByteString a IO ())
It fails with the following:
Couldn't match type `Void' with `()'
Expected type: IO a
Actual type: IO ()
In the expression:
runEffect
$ (undefined :: Producer ByteString IO ())
>-> (undefined :: Pipe ByteString a IO ())
In an equation for `run':
run
= runEffect
$ (undefined :: Producer ByteString IO ())
>-> (undefined :: Pipe ByteString a IO ())
Generally, you need to compose a Producer with a Consumer in order to get an Effect which can be run by runEffect. That's not what you've got here, but fortunately, there are more ways to eliminate a Proxy than just runEffect.
Taking stock of what we have, this composition ends up with a Producer.
pipe :: Producer a IO ()
pipe = (undefined :: Producer ByteString IO ()) >-> (undefined :: Pipe ByteString a IO ())
The Pipes.Prelude module contains many other ways to eliminate Producers like Pipes.Prelude.last
last :: Monad m => Producer a m () -> m (Maybe a)
Probably the most general way to get as out is to use Pipes.Prelude.fold
fold :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Producer a m () -> m b
which is like runEffect except it reduces Producers to their underlying Monad. Since that's what we have it'll work great. Here's how we can implement Pipes.Prelude.head
slowHead = fold (\res a -> res <> First (Just a)) mempty getFirst
Though it's worth noting that slowHead consumes the entire Producer (and thus performs all of the needed effects) while Pipes.Prelude.head performs just the first one. It's much lazier!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With