MVC and pipes-parse

80 views
Skip to first unread message

Tony Day

unread,
Aug 31, 2014, 4:07:27 AM8/31/14
to haskel...@googlegroups.com
Is there any way to use the pipes-parse ecosystem with MVC?

The issue I'm running up against is that an MVC model is (metaphorically at least) a Pipe, but the APIs for Pipes.Parse and friends assume you have a Producer.

tony

Gabriel Gonzalez

unread,
Aug 31, 2014, 11:59:02 AM8/31/14
to haskel...@googlegroups.com, Tony Day
I can add this.  One of the reason that I keep the internals hidden is so that I could add the following function without breaking backwards compatibility:

    ??? :: (Producer a (State s m) () -> Producer b (State s m) ()) -> Model s a b

Then you'd be able to use `pipes-parse` with that signature.  I just need to figure out what to call this function.  Maybe `asGetter`?
--
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 haskell-pipe...@googlegroups.com.
To post to this group, send email to haskel...@googlegroups.com.

Tony Day

unread,
Aug 31, 2014, 9:12:39 PM8/31/14
to haskel...@googlegroups.com, tonyd...@gmail.com
Looks like an asGetter to me.

The other abstractions I find myself reaching for are folds.  Something like:

asFold :: (x -> a -> (State s m) x) -> (State s m) x -> (x -> (State s m) b) -> Producer a (State s m) () -> Model s a b

Which I hack through with:

mvcFold :: Managed (Controller a) -> L.Fold a b -> IO b
mvcFold c (L.Fold step begin done) = do
    x <- runMVC begin (asPipe $ (Pipes.chain (\k -> S.modify (flip step k)))) ((,) <$> pure mempty <*> c)
    return $ done x

And this is a typical usage - hooking up a controller for testing and thus avoid having to rewrite it as a producer.

And, for completion, is there a useful asParser interpretation?  I haven't tried, but it would be nice to have an ability to draw and peek within the model.

Gabriel Gonzalez

unread,
Sep 2, 2014, 6:23:09 PM9/2/14
to haskel...@googlegroups.com, tonyd...@gmail.com
I'm still not clear on why `asFold` takes a `Producer a ...` as an argument.  Why not just the fold?

Gabriel Gonzalez

unread,
Sep 2, 2014, 6:25:23 PM9/2/14
to haskel...@googlegroups.com, tonyd...@gmail.com
Also, there is a useful function in `Pipes.Prelude` which you might find useful:

    Pipes.Prelude.scan :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Pipe a b m r

Using `purely`, that becomes:

    purely Pipes.Prelude.scan :: Monad m => Fold a b -> Pipe a b m r

Or you can use `Pipes.Extras.scan`, which is just a shortcut for the above, if you don't mind the extra dependency.


On 8/31/14, 6:12 PM, Tony Day wrote:

Tony Day

unread,
Sep 2, 2014, 8:09:53 PM9/2/14
to Gabriel Gonzalez, haskel...@googlegroups.com
Yes, of course, you’re right with respect to a fold. I got stuck between using a Fold and using the folds in Pipes.Prelude.

I was thinking of how the folds in the Pipes.Prelude could be used in a model, for example how could you use Pipes.head?

Something like:

asCompute :: (Producer a (State s m) -> (State s m) b) -> Model s a b


Then you would have:

`asCompute Pipes.head` outputting the first element from the controller, and
`asCompute $ purely L.sum` outputting the sum of incoming data.



tony day
tonyd...@gmail.com

Gabriel Gonzalez

unread,
Sep 2, 2014, 10:26:50 PM9/2/14
to Tony Day, haskel...@googlegroups.com
The folds in `Pipes.Prelude` are not designed to be reusable. That's
mainly what the `foldl` library is for, which is the "official" way to
release folds for the `pipes` ecosystem (and as a bonus, for other
ecosystems as well).

Pierre R

unread,
Sep 4, 2014, 7:03:55 AM9/4/14
to haskel...@googlegroups.com, tonyd...@gmail.com


On Wednesday, September 3, 2014 4:26:50 AM UTC+2, Gabriel Gonzalez wrote:
The folds in `Pipes.Prelude` are not designed to be reusable.

Isn't it a bit confusing to mix in a same module "reusable" and "non-reusable" function ?

Gabriel Gonzalez

unread,
Sep 5, 2014, 6:50:20 PM9/5/14
to haskel...@googlegroups.com, tonyd...@gmail.com
Well, it's a little bit more complicated than that.

Some of the folds in `Pipes.Prelude` cannot be implemented in terms of `Pipes.Prelude.fold`, specifically the folds that are lazy.  For example, `Pipes.Prelude.all` terminates on the first `False` value it receives.  Unlike strict folds, lazy folds are not easily combinable, so they are only useful in isolation.

However, some of the folds in `Pipes.Prelude` can be implemented in `Pipes.Prelude.fold`.  I include those mainly to bootstrap new users for simple demonstration purposes.  This is also the same reason that I include `Pipes.Prelude.stdinLn/stdoutLn`, just to give new users a feel for the library before they dive into more complicated idioms.

So for those folds, they definitely
Reply all
Reply to author
Forward
0 new messages