These approaches will definitely work, but I&#39;m worried that creating a whole set of datatypes to represent URLs is overkill. In Yesod (I&#39;m sure many of you have seen) I use quasi-quoting for defining the resources, like such:<div>
<br></div><div>[$mkResources|</div><div>/user:</div><div>    GET: userList</div><div>/user/find/#userid</div><div>    GET: userFind</div><div>/user/name/$username</div><div>    GET: userName</div><div>|]</div><div><br></div>
<div>And so on and so forth. I don&#39;t think defining UserRoute adds much, besides making the job of the library writer a little bit easier by pushing the work off to the user. I think the six lines above succinctly:</div>
<div><br></div><div>* define the valid routes</div><div>* define the data types for arguments</div><div>* define the appropriate mapping to handler functions for each request method</div><div><br></div><div>Chris mentioned earlier to me the idea of using quasi-quoting on the link generation side, perhaps like:</div>
<div><br></div><div>[$link|/user/find/6]</div><div><br></div><div>I think the only piece of the puzzle missing to combine these two together is to have mkResources output something along the lines of:</div><div><br></div>
<div>data RoutePiece = StaticPiece String | IntPiece | StringPiece</div><div>_validRoutes :: [[RoutePiece]]</div><div>_validRoutes =</div><div>  [ [StaticPiece &quot;user&quot;]</div><div>  , [StaticPiece &quot;user&quot;, StaticPiece &quot;find&quot;, IntPiece]</div>
<div>  , [StaticPiece &quot;user&quot;, StaticPiece &quot;name&quot;, StringPiece]</div><div>  ]</div><div><br></div><div>Now if you write</div><div><br></div><div>[$link|/user/find/michael]</div><div><br></div><div>link can look up in _validRoutes that there is no matching route and complain at compile time.</div>
<div><br></div><div>Advantages: less typing by the user.</div><div>Disadvantages: we&#39;ll have to restrict the data types allowed, but in practice I think people will usually want only strings and ints anyway. Also, this approach is more complex.</div>
<div><br></div><div>Michael</div><div><br><div class="gmail_quote">On Tue, Mar 16, 2010 at 7:04 AM, Chris Eidhof <span dir="ltr">&lt;<a href="mailto:chris@eidhof.nl">chris@eidhof.nl</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
I have the feeling it adds a lot of complexity. I agree with you that, if you want modularity, your components should only provide relative URLs and need to be parameterized over how to build an absolute URL. I didn&#39;t think of that problem, and using a custom monad transformer is definitely a solution.<br>

<br>
However, I&#39;m always hesitant to build up stacks of monad transformers, it adds a lot of complexity. I would rather use something like typeclass, but I&#39;m not sure yet how to do that.<br>
<font color="#888888"><br>
-chris<br>
</font><div><div></div><div class="h5"><br>
On 16 mrt 2010, at 14:29, Jeremy Shaw wrote:<br>
<br>
&gt; Hello,<br>
&gt;<br>
&gt; It looks nearly identical, but without the URLT monad transformer.<br>
&gt;<br>
&gt; Instead of ToURL I have the class:<br>
&gt;<br>
&gt; class AsURL a where<br>
&gt;     toURLS :: a -&gt; ShowS<br>
&gt;     fromURLC :: Consumer String (Failing a)<br>
&gt;<br>
&gt; With is basically the same. Except toURLS returns a ShowS instead of [String]. fromURLC consumes a list of [String]. These functions are wrapped up to provide:<br>
&gt;<br>
&gt; toURL :: (AsURL a) =&gt; a -&gt; String<br>
&gt; fromURL :: (AsURL a) =&gt; String -&gt; Failing a<br>
&gt;<br>
&gt; I do not have generics based url printing/parsing, but there is no reason it could not be added. I do have template haskell based code though.<br>
&gt;<br>
&gt; <a href="http://src.seereason.com/urlt/URLT/TH.hs" target="_blank">http://src.seereason.com/urlt/URLT/TH.hs</a><br>
&gt;<br>
&gt; The thing you don&#39;t have is the URLT monad transformer:<br>
&gt;<br>
&gt; <a href="http://src.seereason.com/urlt/URLT/Base.hs" target="_blank">http://src.seereason.com/urlt/URLT/Base.hs</a><br>
&gt;<br>
&gt; Here is why you want it. Imagine you write an image gallery library:<br>
&gt;<br>
&gt; data ImageURL = Upload | ViewImage Int<br>
&gt;<br>
&gt; when you call toURL, you are going to get urls like, /Upload, /ViewImage/1, etc.<br>
&gt;<br>
&gt; Now let&#39;s say I try to use your library in my application. So at first I try:<br>
&gt;<br>
&gt; data MyApp = Upload | FooBar<br>
&gt;<br>
&gt; But when a URL comes in, how do I know if I should decode it as MyApp or ImageURL? Do I try both and see which one succeeds? Except we both have a constructor Upload, so both will succeed. There is no way to tell with Upload the path &quot;/Upload&quot; is referring to.<br>

&gt;<br>
&gt; So now I try:<br>
&gt;<br>
&gt; data MyApp = Upload | FooBar | Images ImageURL<br>
&gt;<br>
&gt; now I know that all incoming urls are decoded as MyApp. But there is still a problem. In my code I could write:<br>
&gt;<br>
&gt;  toUrl (Images (ViewImage 1))<br>
&gt;<br>
&gt; but in your library code, you don&#39;t know anything about the Images constructor. So you just call,<br>
&gt;<br>
&gt; toURL (ViewImage 1)<br>
&gt;<br>
&gt; which generates /ViewImage/1 instead of the required /Images/ViewImage/1.<br>
&gt;<br>
&gt; What I need is someway to tell your library code what prefix to add at the beginning. That is exactly what the URLT monad does. It just holds a function that adds a prefix to the URL.<br>
&gt;<br>
&gt; so in your library you have:<br>
&gt;<br>
&gt; image :: ImageURL -&gt; URLT ImageURL m ()<br>
&gt; image Upload =<br>
&gt;      do ...<br>
&gt;           u &lt;- showURL (ViewImage n)<br>
&gt;           ...<br>
&gt; image (ViewImage num) = ...<br>
&gt;<br>
&gt; Instead of calling toURL, it calls showURL, which adds the context to the URL and then calls toURL on it.<br>
&gt;<br>
&gt; And in my code I have:<br>
&gt;<br>
&gt; myApp :: MyAPP -&gt; URLT MyApp m ()<br>
&gt; mpApp Upload = ...<br>
&gt; myApp FooBar = ...<br>
&gt; myApp (Images subURL) = nestURL Images $ images subURL<br>
&gt;<br>
&gt; the &#39;nextURL Images&#39; adds the Images context to the URLT environment. It can be used to nest multiple levels if needed:<br>
&gt;<br>
&gt;  nestURL A $ nestURL B $ nestURL Images $ showURL (ViewImage 1)<br>
&gt;<br>
&gt; would get turned into something like:<br>
&gt;<br>
&gt;  &quot;/A/B/Images/ViewImage/1&quot;<br>
&gt;<br>
&gt; What do you think?<br>
&gt;<br>
&gt; - jeremy<br>
&gt;<br>
&gt;<br>
&gt; On Tue, Mar 16, 2010 at 3:52 AM, Chris Eidhof &lt;<a href="mailto:chris@eidhof.nl">chris@eidhof.nl</a>&gt; wrote:<br>
&gt; Hey everyone,<br>
&gt;<br>
&gt; I just wrote down some of my ideas about type-safe URL handling on github, it&#39;s at <a href="http://gist.github.com/333769" target="_blank">http://gist.github.com/333769</a><br>
&gt;<br>
&gt; I think it&#39;s similar to what Jeremy is doing with his urlt package [1].<br>
&gt;<br>
&gt; -chris<br>
&gt;<br>
&gt; [1]: <a href="http://src.seereason.com/~jeremy/SimpleSite1.html" target="_blank">http://src.seereason.com/~jeremy/SimpleSite1.html</a><br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; web-devel mailing list<br>
&gt; <a href="mailto:web-devel@haskell.org">web-devel@haskell.org</a><br>
&gt; <a href="http://www.haskell.org/mailman/listinfo/web-devel" target="_blank">http://www.haskell.org/mailman/listinfo/web-devel</a><br>
&gt;<br>
<br>
_______________________________________________<br>
web-devel mailing list<br>
<a href="mailto:web-devel@haskell.org">web-devel@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/web-devel" target="_blank">http://www.haskell.org/mailman/listinfo/web-devel</a><br>
</div></div></blockquote></div><br></div>