April 3rd, 2009 (09:32 pm)

I'm writing this at work, so don't expect it to make too much sense.



There was another flurry of blog posts about writing generic traversals over types of the following general form:



data List a f = Nil | Cons a f newtype Mu f = InF { outF :: f (Mu f) }

data Vec a n where Nil :: Vec a 0 Cons a (Vec a m) :: Vec a (m+1)

data Mu where InF : (k:**) -\\> (f : * -> k) -\> f (Mu f) -> Mu f

mu f : (k:**) -\> (k -> k) -> k mu f = f (mu f)

mu f = f (Wrap (mu f))

These are really neat. But...Haskell doesn't directly support this. Sure, you could write all your types in this really weird style, and you could even create some Template Haskell code to automatically generate all the smart constructors to make it usable. You could probably write a bunch of clever template code to handle GADTs.Okay, so how about dependent types? The sample type (making up syntax as I go) is:It should be clear that we can't replace the fully applied type; we have to replace Vec. But that can't be done by Mu, because Mu wants something of kind * -> *, but the modified Vec has kind * --> * --> * --> *. If the extra parameter is added up front, we can use kind-level polymorphism.but that doesn't work, because f (Mu f) isn't inhabited unless its kind is *. Declaring the result to be of kind k wouldn't fix it either. Okay, let's try type-level functions.This works, but only if I admit infinite types. A quick modification should fix it.But now I don't know how to define Wrap!