Sent from my iPad
On Nov 15, 2011, at 7:18 PM, wren ng thornton <w...@freegeek.org> wrote: > On 11/15/11 12:33 PM, Yitzchak Gale wrote: >> Simon Peyton-Jones wrote: >>>>>> Trouble is, what type does this have? >>>>>> f x = x {} >> >> Malcolm Wallace wrote: >>>>> f :: a -> a >> >> Ian Lynagh wrote: >>>> That wouldn't help the original poster, as it is incompatible with >>>> f :: Foo Clean -> Foo Dirty >> >> Only because in that expression the type of x is not known. >> >>>>>> ...the whole feature of type-changing update is (as you know) >>>>>> a bit obscure and not widely used, so it'd be adding >>>>>> complexity to an already-dark corner. >> >> To me, at least, that is surprising. The report implies that >> record updates are just sugar for the given case expression. >> Whether or not it changes a type parameter seems >> unimportant. >> >> In fact, I would even advocate adding a line of explanation >> in the Report that this is a convenient way of copying >> a value from an ADT to itself with a different type >> as its parameter. I agree with Malcolm that this is >> analogous to using empty record syntax in a pattern >> to avoid hard-coding the number of parameter to >> a constructor. >> >> I usually avoid using the combination of type parameters and >> record syntax altogether, mainly because this obvious syntax >> doesn't work. Perhaps that's the reason why type-changing >> update is not widely used. >> >> (Admittedly, I didn't think of Herbert's trick. But doesn't >> that seem like somewhat of an ugly hack?) >> >> Are you hesitant because of implementation difficulty, >> or only because you are worried about the semantics >> being confusing? In my opinion, it's more confusing >> the way it is now. > > For what it's worth, I do the exact same thing in the project I've been > working on. The phantom type is a clean/dirty bit even :) > > It's an incredibly helpful thing to have for records. Especially for the > context I'm in: I'm generating summary data over gobs of input, but the input > can come incrementally. So long as the core of the summary is correct, then I > don't care about maintaining the cache fields while I'm just shoveling data > in; but I do want to make sure the caches are valid before I try to get any > information out. This is exactly the sort of type-level hackery which makes > Haskell a joy to work in and other languages such a pain. > > So far I've just defined helper functions to adjust the phantom type[1], each > of which is implemented by (\x -> x { foo = foo x }). It's a horrible hack, > but at least it's hidden away in library functions instead of something I > have to look at. The annoying part is that when I adjust the members of the > records, if I remove or rename foo then I have to fix all those coercion > functions too. > My biggest issue is loss of sharing, but you could always use castFoo = asTypeOf unsafeCoerce $ \x -> x { foo = foo x } to maximize sharing, but that doesn't help with the code rewriting, Or less horrifically just carry the phantom in a newtype wrapper wrapped around your record, and cast by putting it on and taking it off, which also maximizes sharing in exchange for newtype noise on access. _______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users