Thank you!<div>Working implementation is even more than I've expected.</div><div><br></div><div><br><br><div class="gmail_quote">2011/4/28 Felipe Almeida Lessa <span dir="ltr"><<a href="mailto:felipe.lessa@gmail.com">felipe.lessa@gmail.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">On Thu, Apr 28, 2011 at 1:10 PM, Felipe Almeida Lessa<br>
<div class="im"><<a href="mailto:felipe.lessa@gmail.com">felipe.lessa@gmail.com</a>> wrote:<br>
> On Thu, Apr 28, 2011 at 12:09 PM, Felipe Almeida Lessa<br>
> <<a href="mailto:felipe.lessa@gmail.com">felipe.lessa@gmail.com</a>> wrote:<br>
>> I foresee one problem: what is the leftover of 'manyToOne xs' if each<br>
>> x in xs needs different lengths of input?<br>
>><br>
>> One possible untested-but-compiling solution:<br>
> [snip]<br>
><br>
> Like I said, that manyToOne implementation isn't very predictable<br>
> about leftovers. But I guess that if all your iteratees consume the<br>
> same input OR if you don't care about leftovers, then it should be<br>
> okay.<br>
<br>
</div>Sorry for replying to myself again. =)<br>
<br>
I think you can actually give predictable semantics to manyToOne:<br>
namely, the leftovers from the last iteratee are returned. This new<br>
implementation should be better:<br>
<br>
import Data.Monoid (mappend)<br>
<div class="im">import qualified Data.Enumerator as E<br>
<br>
manyToOne :: Monad m => [E.Iteratee a m b] -> E.Iteratee a m [b]<br>
</div>manyToOne is = E.Iteratee $ mapM E.runIteratee is >>=<br>
E.runIteratee . go<br>
where<br>
go [step] = fmap (:[]) (E.returnI step)<br>
go (E.Yield b _ : xs) = fmap (b:) (go xs)<br>
go (E.Error exc : _) = E.returnI (E.Error exc)<br>
go (E.Continue f : xs) = E.continue $ go' (E.Continue f : xs)<br>
go [] = return []<br>
<br>
go' xs stream = manyToOne $ feed xs<br>
where<br>
feed [E.Yield b s] = [E.yield b (s `mappend` stream)]<br>
feed (E.Continue f : ys) = f stream : feed ys<br>
feed (step : ys) = E.returnI step : feed ys<br>
feed [] = []<br>
<br>
With the same test as before:<br>
<div class="im"><br>
*Main> E.run $ E.enumList 1 [5 :: Int, 6, 7] E.$$ manyToOne [return 1,<br>
maybe 2 id `fmap` E.head, return 3, maybe 4 id `fmap` (E.head >><br>
E.head)] >>= \xs -> (,) xs `fmap` E.head<br>
Right ([1,5,3,6],Just 7)<br>
*Main> E.run $ E.enumList 10 [5 :: Int, 6, 7] E.$$ manyToOne [return<br>
1, maybe 2 id `fmap` E.head, return 3, maybe 4 id `fmap` (E.head >><br>
E.head)] >>= \xs -> (,) xs `fmap` E.head<br>
</div>Right ([1,5,3,6],Just 7)<br>
<br>
When the last iteratee doesn't consume anything:<br>
<div class="im"><br>
*Main> E.run $ E.enumList 1 [5 :: Int, 6, 7] E.$$ manyToOne [return 1,<br>
maybe 2 id `fmap` E.head, return 3, maybe 4 id `fmap` (E.head >><br>
</div>E.head), return 10] >>= \xs -> (,) xs `fmap` E.head<br>
Right ([1,5,3,6,10],Just 5)<br>
<div class="im">*Main> E.run $ E.enumList 10 [5 :: Int, 6, 7] E.$$ manyToOne [return<br>
1, maybe 2 id `fmap` E.head, return 3, maybe 4 id `fmap` (E.head >><br>
</div>E.head), return 10] >>= \xs -> (,) xs `fmap` E.head<br>
Right ([1,5,3,6,10],Just 5)<br>
<br>
HTH,<br>
<br>
--<br>
<font color="#888888">Felipe.<br>
</font></blockquote></div><br></div>