Minor update: I think that YAML syntax for these kinds of routes is a little bit verbose; any thoughts on this syntax:<div><br></div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">/                    Home       GET</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">/user/#userid        User       GET PUT DELETE</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">/static              Static     StaticRoutes staticRoutes</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">/foo/*slurp          Foo</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">/bar/$barparam       Bar</font></div>
<div><br></div>First column is the pattern, second is the constructor name, and after that you have three possibilities:</div><div><br></div><div>Nothing is a handler function for any request method. Above, the fourth and fifth entries.</div>
<div>A list of request methods will allow a handler function for each request method. Above, the first and second entries.</div><div>A datatype and function name, allowing a subsite datatype and subsite function. Above,the third entry. I&#39;ll need to develop this one a bit more.</div>
<div><br></div><div>Michael</div><div><br></div><div><div class="gmail_quote">On Mon, Mar 29, 2010 at 4:17 PM, Michael Snoyman <span dir="ltr">&lt;<a href="mailto:michael@snoyman.com">michael@snoyman.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br><br><div class="gmail_quote"><div class="im">On Mon, Mar 29, 2010 at 11:37 AM, Jeremy Shaw <span dir="ltr">&lt;<a href="mailto:jeremy@n-heptane.com" target="_blank">jeremy@n-heptane.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>On Mon, Mar 29, 2010 at 12:16 PM, Michael Snoyman <span dir="ltr">&lt;<a href="mailto:michael@snoyman.com" target="_blank">michael@snoyman.com</a>&gt;</span> wrote:<br></div><div class="gmail_quote"><div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote"><div>The reason I&#39;m unexcited is that I never would have dreamed of defining my routes that way. I don&#39;t feel like drawing out this point too much, because you clearly *would* define your routes that way. However, just to draw the distinction in how I would do things differently, I&#39;ll use an example of mine that you quoted earlier:</div>



<div><br></div><div><span style="font-family:arial, sans-serif;font-size:13px;border-collapse:collapse"><div><div>instance Yesod PB where</div><div>    resources = [$mkResources|</div><div>/:</div>
<div>    GET: indexHandler</div><div>/entries/$entryId:</div><div>    GET: entry</div><div>/entries/$entryId/$filename:</div><div>    GET: media</div><div>/feed:</div><div>    GET: feed</div><div><br></div></div><div>If I were to convert this to a datatype, it would be:</div>



<div><br></div><div>data PBRoutes = Home | Entry String | File String String | Feed</div></span></div></div></blockquote><div><br></div></div><div><div>You do still have nested data-types here. Namely the String. In this case it is trivial to handle by hand, but it does pose a problem for things like TH and Regular. That is why I had PathInfo in the original code in the first place.. I couldn&#39;t figure out how to write the TH code with out it.</div>


</div><div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_quote"><div><span style="font-family:arial, sans-serif;font-size:13px;border-collapse:collapse"><div>


I simply wouldn&#39;t nest a datatype inside any of the constructors. I understand that you want to do this in some circumstances, but I would simply &quot;duplicate&quot; the parsing code for the Entry and File constructors, since I find that parsing code trivial. In particular:</div>



<div><br></div><div>parsePB [&quot;entries&quot;, eid] = Entry eid</div><div>parsePB [&quot;entries&quot;, eid, filename] = File eid filename</div><div><br></div><div>I don&#39;t see a need for providing a sophisticated parser.</div>


</span></div></div></blockquote><div><br></div></div><div>If you are going to duplicate the code instead of calling fromPathSegments, then you don&#39;t really need PathInfo at all, right? The current code is designed so that you are not forced to use PathInfo.</div>


<div><br></div></div></blockquote></div><div>Right, I just didn&#39;t understand the purpose of PathInfo; you&#39;ve explained it very clearly now, thank you.</div><div><div></div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div class="gmail_quote"><div></div><div>We have:</div><div><br></div><div>data Site = Site { ...</div><div>                           , parsePathSegments  :: [String] -&gt; Either String url</div><div>                           }</div>

<div><br>
</div><div>And you can do:</div><div><br></div><div>Site { parsePathSegments = parsePB }</div><div><br></div><div>The only real reason to have PathInfo is to build composable parsers as far as I can tell. So, I guess maybe you are suggesting that PathInfo should be a separate package? I don&#39;t see a big win here since we will depend on parsec 2 anyway, and since web-routes-wai would need to depend on it anyway to provide the wai related functions that do use PathInfo..</div>


<div><br></div><div>I did add a new parser combinator though:</div><div><br></div><div>patternParse :: ([String] -&gt; Either String a) -&gt; URLParser a</div><div><br></div><div>so you can do:</div><div><br></div><div>fromPathSegments = patternParse parsePB</div>


<div><br></div><div>patternParse consumes all the remaining segments and passes them to parsePB.</div><div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
<div>So, I&#39;ve thought about the syntax for this, and I have this idea in mind.</div><div><br></div><div><span style="font-family:arial, sans-serif;font-size:13px;border-collapse:collapse"><div>
$(createRoutes MyRoutes [$parseRoutes|</div><div>/:</div><div>  name: Home</div><div>  methods: [GET]</div><div>/user/#userid:</div><div>  name: User</div><div>  methods: [GET, PUT, DELETE]</div><div>/static:</div><div>  name: Static</div>



<div>  subsite: StaticRoutes</div><div>  dispatch: staticRoutes</div><div>|])</div><div><br></div><div>This would generate a datatype:</div><div><br></div><div>data MyRoutes = Home | User Integer | Static StaticRoutes</div>


</span></div></blockquote><div><br></div><div><br></div></div><div>So your idea is to generate the data-type from the routes, rather than try to map the routes onto an existing datatype? </div><div><br></div><div>Your approach sounds easier. The advantage of the latter is that you could change the look of the url with out having to go change all your code that uses the URL type.. Not sure how doable the latter is though.</div>

<div>
<div><br></div></div></div></blockquote></div></div><div>Well, I&#39;ve started implementing it: it can now generate the data types, but doesn&#39;t do the parsing, building and dispatching functions. Those should be fairly simple, but I&#39;m just running out of time (Passover seder in a few hours...). Thought I&#39;d let you have a sneak preview:</div>

<div><br></div><div><a href="http://github.com/snoyberg/web-routes-quasi" target="_blank">http://github.com/snoyberg/web-routes-quasi</a></div><div class="im"><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div class="gmail_quote"><div><div></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><span style="font-family:arial, sans-serif;font-size:13px;border-collapse:collapse"><div>


Handler functions would be getHome, getUser, putUser, deleteUser. Static would be a pluggable subsite; I&#39;d have to play around with the syntax of that a bit. Also, this will allow *any* type of application, not just wai (I want this to be as general as possible).</div>


</span></div></blockquote><div><br></div></div><div>right. I see no reason for it to be wai specific.</div><div><br></div><div>Speaking of wai, there is a bug in wai-extra in SimpleServer. It does not put a space between the status code and the status message</div>


<div><br></div><div><div>~/n-heptane/projects/haskell/web-routes $ curl -v <a href="http://localhost:3000/MyHomeoeu" target="_blank">http://localhost:3000/MyHomeoeu</a></div><div>* About to connect() to localhost port 3000 (#0)</div>

<div>
*   Trying ::1... Connection refused</div><div>*   Trying 127.0.0.1... connected</div><div>* Connected to localhost (127.0.0.1) port 3000 (#0)</div><div>&gt; GET /MyHomeoeu HTTP/1.1</div><div>&gt; User-Agent: curl/7.19.5 (i486-pc-linux-gnu) libcurl/7.19.5 OpenSSL/0.9.8g zlib/<a href="http://1.2.3.3" target="_blank">1.2.3.3</a> libidn/1.10 libssh2/0.18</div>


<div>&gt; Host: localhost:3000</div><div>&gt; Accept: */*</div><div>&gt; </div><div>&lt; HTTP/1.1 404Not Found</div><div>* no chunk, no close, no size. Assume close to signal end</div><div><br></div><div>Note the second to last line.</div>


<div><br></div><font color="#888888"><div>- jeremy</div></font></div></div>
</blockquote></div></div><br><div>Thanks for catching that, bug fix is (as you can imagine) just one line; I&#39;ll upload when I have a free moment.</div><div><br></div><font color="#888888"><div>Michael</div>
</font></blockquote></div><br></div>