On Fri, Mar 26, 2010 at 6:01 PM, Jeremy Shaw <jeremy@n-heptane.com> wrote:
A variation which is more obviously hierarchical in nature:

data User = User LastName FirstName
data Section = Recent | TopRated
data UserHomeURL = Wall Section | Profile
data UserURL = ViewHome User UserHome

Which would be used to construct urls like:

/shaw/jeremy/wall/recent
/snoyman/michael/profile

To expand on this slightly let's pretend you first implemented a module that supported a single user:

data Section = Recent | TopRated
data UserHomeURL = Wall Section | Profile

And you release that as a library.

Then in another app, which supports multiple users, you want to use it. So you create:
 
data User = User LastName FirstName
data UserURL = ViewHome User UserHome

That seems pretty sensible. After all the half the point of this library is to be able to build reusable components. Because we are reusing a component, we can not modify the UserHome portion of the URL. But we still need some way to specify which user's home we are looking at. The above types seem sensible for that.

You have similar structures in your photo blog app:

--------
instance Yesod PB where
    resources = [$mkResources|
/:
    GET: indexHandler
/entries/$entryId:
    GET: entry
/entries/$entryId/$filename:
    GET: media
/feed:
    GET: feed

...
------

A reasonable URL type for that might be:

data EntryId = ...
data PhotoBlogURL = BlogHome | Entry EntryId | Media EntryId FileName | Feed

Where Media has two arguments to it's constructor. You can't really factor that out, can you? You could fake it like:

data PhotoBlogURL = BlogHome | Entry EntryId | Media (EntryId, FileName) | Feed

But that does not really buy you anything, because when you write the Media parser, you still have to know how many segments EntryId consumes, and how many FileName consumes. 

perhaps entryid is:

data EntryId = EntryId { year :: Int
                                     , month :: Int
                                     ,