[web-devel] Type-safe URL handling

Jeremy Shaw jeremy at n-heptane.com
Tue Mar 16 09:29:18 EDT 2010


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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/web-devel/attachments/20100316/8fd07efa/attachment-0001.html


More information about the web-devel mailing list