[web-devel] ANN: url-generic-0.1: Parse/format generic key/value URLs from record data types.

Jeremy Shaw jeremy at n-heptane.com
Tue Jun 21 02:02:21 CEST 2011

On Mon, Jun 20, 2011 at 6:12 PM, Christopher Done
<chrisdone at googlemail.com> wrote:
>> You allow the fields to be specified in any order -- but that makes it
>> difficult to support record types that contain other record types,
>> doesn't it?
> Does it? Why?
> /foo/x/1/y/a/1/b/2/z/2 seems no more ambiguous than /foo/y/b/1/a/2/z/2/x/1
> I'd think the problem stopping embedded types is optional fields.

Yeah actually, it should work out ok. But you will need to take a
rather different approach to parsing.

It just won't be fun to write the code. But that is your job not mine :p

So you have:


I believe the type that comes from is:

> data Foo = Foo { x :: Int
>                , y :: Y
>                , z :: Int
>                }
> data Y = Y { a :: Int
>            , b :: Int
>            }

So, the current SYB stuff is going to have issues with this I think.
It will first look at the 'foo' for the 'Foo' constructor, and then
try to split the rest of the path segments up into key/value pairs via

 /y/a -- oops. things went wrong here

Well, that does not really work. We can hack around the off-by-one
issue by introducing another y for the Y constructor:


That gives us:


so now we get:


which seems ok. But what if we extend Foo to have a second Y field:

> data Foo = Foo { w :: Y
>                , x :: Int
>                , y :: Y
>                , z :: Int
>                }

giving us:


now when split it up we get:


Oops. Now we have a & b twice. That doesn't really work. Clearly we
need to know if the a & b are associated with the w field or the y

So, that means urlToAssoc is not going to cut it -- we need to replace
it with something that understands the types involved.

In order to consume:


We need to parse the segments in the order they appear.

step 1: /foo

We see /foo. We know now that we are looking for four fields, w, x, y and z.

step 2: /w

We know we are parsing Y type, so we call the parseCons for Y. That consumes:


and leaves us with:


step 3:

We do the same thing for /x, /y, and /z.

step 4:

Then we assemble the fields in the right order and apply the Foo
constructor to them.

We have to be careful to handle the cases where the incoming url is
missing a field or (incorrectly) has a field twice.

Or maybe I am missing something obvious. I have not thought about this too much.

I'll read the rest of your reply later. I have some stuff I need to do now.

- jeremy

More information about the web-devel mailing list