[Haskell-cafe] "mapping" an Enumerator

Kannan Goundan kannan at cakoose.com
Wed Dec 21 13:14:22 CET 2011


Michael Snoyman wrote:

> On Wed, Dec 21, 2011 at 12:59 PM, Kannan Goundan <kannan at cakoose.com>
> wrote:
>> Michael Snoyman wrote:
>>
>>> On Wed, Dec 21, 2011 at 12:35 PM, Kannan Goundan <kannan at cakoose.com>
>>> wrote:
>>>> I'm using the Data.Enumerator library.  I'm trying to write a "map"
>>>> function that converts an Enumerator of one type to another.
>>>> Something like:
>>>>
>>>>   mapEnum :: Monad m =>
>>>>          (a -> b) ->
>>>>          Enumerator a m r ->
>>>>          Enumerator b m r
>>>>
>>>> Any hints?
>>>>
>>>> (My exact use case is that I have a ByteString enumerator and I need
>>>> to pass it to something that requires a Blaze.Builder enumerator.)
>>>>
>>>>
>>>> _______________________________________________ Haskell-Cafe mailing
>>>> list
>>>> Haskell-Cafe at haskell.org
>>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>>
>>> You can use the Data.Enumerator.List.map function to create an
>>> Enumeratee, and then the Data.Enumerator.$= operators to join them
>>> together. Something like:
>>>
>>> mapEnum f enum = enum $= EL.map f
>>
>> I tried something like that but the resulting type isn't quite what I'm
>> looking for.
>>
>>   mapEnum :: Monad m =>
>>         (a -> b) ->
>>         Enumerator a m (Step b m r) ->
>>         Enumerator a m r
>>
>> (BTW, Michael, my exact use case is that I have ByteString enumerators,
>> but your HTTP-Enumerator library wants Blaze.Builder enumerators :-)
>>
>>
>> _______________________________________________ Haskell-Cafe mailing
>> list
>> Haskell-Cafe at haskell.org
>> http://www.haskell.org/mailman/listinfo/haskell-cafe
> 
> Huh, I'm stumped ;). John: is this possible in enumerator?
> 
> In general though: do you need precisely that type signature? Most of
> the time, Enumerators have polymorphic return types. It might be a
> problem from http-enumerator requiring (), but I *think* we can work
> around that.
> 
> Michael

You're right -- now that I think about it, I don't really care what the 
type of 'r' is.  (Boy, I could have saved several hours today if I had 
realized that earlier :-)

But yeah, I'm having trouble matching the () in http-enumerator's 
interface.  (I wonder if it's because I'm trying to use a fully concrete 
helper type 'MyRequestBody'):

  data MyRequestBody = MyRequestBody Int64 (Enumerator ByteString IO ())

  myHttp :: URL -> MyRequestBody -> IO ()
  myHttp url (MyRequestBody len bsEnum) = ...
    where
      builderEnum = mapEnum BlazeBS.fromByteString bsEnum
      reqBody = RequestBodyEnum len builderEnum

GHC tells me that mapEnum expects bsEnum to be:

   Enumerator ByteString IO (Step Blaze.Builder IO ())

But it is actually:

   Enumerator ByteString IO ()

Wonder if I can use a "forall" in the definition of MyRequestBody to fix 
things without introducing an externally visible type parameter...

Also, thanks for your help so far!




More information about the Haskell-Cafe mailing list