I realized that just as I was posting the code. Thanks.

On Thu, May 15, 2014 at 6:29 PM, Gabriel Gonzalez <[email protected]>wrote:

>  Have you considered using a `Pipe` instead of a `Fold`?  In other words:
>
>     interesting :: Int -> (a -> Bool) -> Pipe a [a] m r
>
> It seems like a more natural fit for your problem.  Basically it uses
> `await` to get the next element, and it `yield`s each successive stanza
> that it computes.
>
>
> On 5/14/14, 5:31 PM, Alex Rozenshteyn wrote:
>
>  What I ended up writing (not cleaned up at all, and not exactly solving
> the problem posed; CRAPLed <http://matt.might.net/articles/crapl/>, if
> you will) can be found here: http://lpaste.net/104155
>
>  I used a monadic fold and the Writer monad, though looking back on it, I
> feel like Pipes would be a natural fit. I'm keeping a buffer just big
> enough to know what to output at each step in the consumption of the list.
>
>  One problem I had was that I misremembered how scan works; for some
> reason I thought that `scan list` was `tails` and not `inits`.
>
>
>
> On Wed, May 14, 2014 at 7:50 PM, Gabriel Gonzalez <[email protected]>wrote:
>
>>  Actually, there's not a good way to do this using `Foldl` because the
>> fold does not have access to elements ahead of it in the stream.
>>
>> However, there's a pretty simple solution in terms of ordinary list
>> functions:
>>
>>     import Data.List (tails)
>>
>>
>>     takeInteresting :: Int -> (a -> Bool) -> [a] -> [a]
>>      takeInteresting n pred = go n
>>       where
>>         -- go :: Int -> [a] -> [a]
>>         go n as =
>>             if n <= 0
>>             then []
>>             else let (prefix , suffix ) = break pred as
>>                      (prefix', suffix') = case suffix of
>>                          []      -> (prefix, suffix)
>>                          s:uffix -> (prefix ++ [s], uffix)
>>                  in  prefix' ++ go (n - 1) suffix'
>>
>>     scanInteresting :: Int -> (a -> Bool) -> [a] -> [[a]]
>>     scanInteresting n pred = map (takeInteresting n pred) . tails
>>
>> Here's an example usage:
>>
>>     >>> scanInteresting 2 (== 0) [1, 2, 0, 3, 4, 0, 5, 6, 0]
>>
>> [[1,2,0,3,4,0],[2,0,3,4,0],[0,3,4,0],[3,4,0,5,6,0],[4,0,5,6,0],[0,5,6,0],[5,6,0],[6,0],[0],[]]
>>
>>
>>
>> On 5/11/14, 9:40 AM, Alex Rozenshteyn wrote:
>>
>>      Only tangentially related, but still, close enough that I feel like
>> it's a follow-up, and tricky enough that I feel like I should ask someone
>> else.
>>
>>  This is a Foldl question, so if there's a better place to ask it, please
>> let me know.
>>
>>  Some context, which can mostly be safely ignored, but I'm providing for
>> motivation in case my explanation is not clear:
>>
>>  I'm trying to make Anki flashcards to memorize "The Love Song of J.
>> Alfred Prufrock". My input format is the text of the poem (slightly
>> preprocessed), and my output formate is a newline separated file with some
>> formatting on each line. Each line defines a flashcard with a hole (a cloze
>> deletion). I would like sufficient context; in this case, it's 5 lines or
>> to the beginning of the stanza, whichever is longer.
>>
>>  </context>
>>
>>  What I want to write is a variant on a take function that takes the
>> first n "interesting" elements and any uninteresting ones interspersed;
>> that is
>>
>>  takeInteresting :: Int -> (a -> Bool) -> [a] -> [a]
>>
>>  such that
>>
>> length . filter p . takeInteresting n p == n
>>  isPrefixOf (takeInteresting n p xs) xs
>>
>>  If I understand correctly, I can write this as a fold and then use a
>> scan to apply it at every starting point.
>>
>>  My question is how best to write this fold.
>>
>> My ad-hoc approach was to use a decorate-doStuff-undecorate pattern where
>> I would count the number of interesting elements, but it wasn't very
>> compositional; I expect there's a better approach.
>>
>>  Thank you.
>>
>>
>> On Thu, Mar 6, 2014 at 12:43 AM, Gabriel Gonzalez 
>> <[email protected]>wrote:
>>
>>>  The trick is to combine `pipes` with the `foldl` library.  In fact,
>>> given any `Fold`, you can convert it into a scanning pipe like this:
>>>
>>>     convert :: Monad m => Fold a b -> Pipe a b m r
>>>     convert = Control.Foldl.purely Pipes.Prelude.scan
>>>
>>> So now you have a smaller problem: write a fold for a moving average of
>>> a stream of numbers.  It turns out that there is a nice way to do this in
>>> O(1) space if you do an exponential moving average:
>>>
>>> http://lpaste.net/100765
>>>
>>> You can also do an ordinary moving average, too, but that requires O(N)
>>> space (where N is the window size).  It basically involves storing the last
>>> N elements as the fold's internal state.
>>>
>>> The `foldl` library is easy to learn.  Just read the module header here
>>> and the documentation for the `Fold` type:
>>>
>>> http://hackage.haskell.org/package/foldl-1.0.2/docs/Control-Foldl.html
>>>
>>> Now, technically, you could do all of this without using the `foldl`
>>> library at all, just by passing the folding logic directly to
>>> `Pipes.Prelude.scan`, but by using `foldl` you make it really easy to add
>>> additional metrics to your `Fold` while still passing over the data just
>>> once.
>>>
>>>
>>> On 3/5/2014 8:01 AM, Alex Rozenshteyn wrote:
>>>
>>>  I feel like I must be missing something rather basic, but I have been
>>> trying to figure out how to use pipes to compute a moving average of a
>>> stream of numbers. I've written code to do the EWMA, but I can't figure out
>>> how to do the sliding window. It doesn't help that I'm a bit of a pipes
>>> beginner.
>>>
>>> Advice is welcome and appreciated.
>>>
>>> Thank you.
>>>  --
>>>  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].
>>>
>>>
>>>
>>
>>
>> --
>>            Alex R
>>
>>
>>
>
>
> --
>            Alex R
>
>
>


-- 
          Alex R

-- 
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