My new version has two typeclasses, I'll copy them in their entirety here:
class IsRelPath a where
toRelPath :: a -> RelPath
fromRelPath :: RelPath -> Maybe a
class IsRelPath (Routes a) => WebPlug a where
type Routes a
dispatch :: a -> Routes a -> (Routes a -> AbsPath) -> Application
I think we all agree that IsRelPath 1) needs to exist and 2) should be called something better than that. I would say that it's useful to have dispatch as part of a typeclass, which is what WebPlug now is. What makes this typeclass so convenient is that any instance of WebPlug is *self contained*. There's no need to keep track of which subapps require which arguments.
I am not really clear wath the benefit for WebPlug is -- it seems to me that it is just adding more boilerplate..
I added two new modules to URLT, namely URLT.Wai and URLT.Dispatch.
I think implemented your little blog demo twice. Once where I didn't use dispatch, and once were I did. The code for that is here:
It seemed like using dispatch did not get rid of or simplify anything, it just added more boiler plate, type classes, and used extensions (type families) that a lot of people don't understand yet.
And instead of writing something short a straigt-forward like:
handleWai mkAbs fromAbs (mySite now)
I had to write the longer:
handleWai mkAbs fromAbs (dispatch (SiteArgs (BlogArgs now)))
And on the handler end, it hide useful information in the type signature and required more constructor matching. Instead of:
myBlog :: UTCTime -> (BlogURL -> String) -> BlogURL -> Application
myBlog now mkAbs BlogHome _request =
I have:
myBlogD :: BlogArgs -> (BlogURL -> String) -> BlogURL -> Application
myBlogD (BlogArgs now) mkAbs BlogHome _request =
In order to know the type of 'now' I have to go look somewhere else. In 'myBlog' it was right there in the type signature.
So, I guess I do not yet see the value of Dispatch. On the plus side, it doesn't seem like I have to use it if I don't like it. But I am curious if I am missing something useful here..
One advantage is that I can do:
:info Dispatch
in GHCi, and see all the Dispatch instances that are available. But I'm not sure that really makes it worth the effort.
- jeremy
p.s. The WaiExample does not use AsURL / IsRelPath, because that is really a completely orthogonal issue, and I wanted to cut out anything that was not relevant.