[web-devel] Yesod's Route as a data family

Matt Brown matt at softmechanics.net
Wed Nov 10 07:43:59 CET 2010

Hi all,

I'm trying to create a yesod subsite with "private" urls.  The subsite
exports widgets which reference the urls, but the urls are not
intended to be referenced from the master site handlers directly.  In
order for this to work, the sub site needs to know how to translate
it's urls into master urls.  I didn't like passing the subsite route
as a parameter to every widget function, so I tried a class:

class YesodSubRoute sub master where
  subRoute :: Route sub -> Route master

After confronting the dreaded "type families are not injective" error
(i.e. "sub" cannot be inferred from "Route sub", etc), I rewrote it

class YesodSubRoute sub master where
  subRoute :: sub -> master -> Route sub -> Route master

This works, but seems a bit cludgy to me.  Looking closer, I realized
that mkYesodGeneral never reuses types for Route instances, which
means Route actually is injective (as long as instances are only being
defined by mkYesodGeneral), the typechecker just doesn't know it.

As an experiment, I changed Route to a data family.  It went rather
smoothly, and I was able to use my original definition of
YesodSubRoute (instances of which could in theory be generated by
mkYesodGeneral).  The only trouble I've had is exporting Route
instance constructors imported from another package (specifically
yesod-auth in my case), which means every module referencing auth
routes has to import Yesod.Helpers.Auth).

Relevant commits are below.  Does this seem like a sensible approach?
Are there better alternatives?



More information about the web-devel mailing list