[web-devel] Type-safe URL handling

Chris Eidhof chris at eidhof.nl
Tue Mar 16 10:04:45 EDT 2010


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't think of that problem, and using a custom monad transformer is definitely a solution.

However, I'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'm not sure yet how to do that.

-chris

On 16 mrt 2010, at 14:29, Jeremy Shaw wrote:

> Hello,
> 
> It looks nearly identical, but without the URLT monad transformer. 
> 
> Instead of ToURL I have the class:
> 
> class AsURL a where
>     toURLS :: a -> ShowS
>     fromURLC :: Consumer String (Failing a)
> 
> 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:
> 
> toURL :: (AsURL a) => a -> String
> fromURL :: (AsURL a) => String -> Failing a
> 
> 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. 
> 
> http://src.seereason.com/urlt/URLT/TH.hs
> 
> The thing you don't have is the URLT monad transformer:
> 
> http://src.seereason.com/urlt/URLT/Base.hs
> 
> Here is why you want it. Imagine you write an image gallery library:
> 
> data ImageURL = Upload | ViewImage Int
> 
> when you call toURL, you are going to get urls like, /Upload, /ViewImage/1, etc.
> 
> Now let's say I try to use your library in my application. So at first I try:
> 
> data MyApp = Upload | FooBar
> 
> 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 "/Upload" is referring to.
> 
> So now I try:
> 
> data MyApp = Upload | FooBar | Images ImageURL
> 
> now I know that all incoming urls are decoded as MyApp. But there is still a problem. In my code I could write:
> 
>  toUrl (Images (ViewImage 1))
> 
> but in your library code, you don't know anything about the Images constructor. So you just call,
> 
> toURL (ViewImage 1)
> 
> which generates /ViewImage/1 instead of the required /Images/ViewImage/1.
> 
> 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.
> 
> so in your library you have:
> 
> image :: ImageURL -> URLT ImageURL m ()
> image Upload = 
>      do ...
>           u <- showURL (ViewImage n)
>           ...
> image (ViewImage num) = ...
> 
> Instead of calling toURL, it calls showURL, which adds the context to the URL and then calls toURL on it.
> 
> And in my code I have:
> 
> myApp :: MyAPP -> URLT MyApp m ()
> mpApp Upload = ...
> myApp FooBar = ...
> myApp (Images subURL) = nestURL Images $ images subURL 
> 
> the 'nextURL Images' adds the Images context to the URLT environment. It can be used to nest multiple levels if needed:
> 
>  nestURL A $ nestURL B $ nestURL Images $ showURL (ViewImage 1) 
> 
> would get turned into something like:
> 
>  "/A/B/Images/ViewImage/1"
> 
> What do you think?
> 
> - jeremy
> 
> 
> On Tue, Mar 16, 2010 at 3:52 AM, Chris Eidhof <chris at eidhof.nl> wrote:
> Hey everyone,
> 
> I just wrote down some of my ideas about type-safe URL handling on github, it's at http://gist.github.com/333769
> 
> I think it's similar to what Jeremy is doing with his urlt package [1].
> 
> -chris
> 
> [1]: http://src.seereason.com/~jeremy/SimpleSite1.html
> 
> _______________________________________________
> web-devel mailing list
> web-devel at haskell.org
> http://www.haskell.org/mailman/listinfo/web-devel
> 



More information about the web-devel mailing list