From: <bri...@cs...> - 2008-01-22 16:34:37
|
Justin Bailey wrote: > I have a value which is a query, Query (Rel r). I would like to > recover the columns and types used in the query. The ShowLabel > instance looks like the way to go, but I was not sure how to recover > the ReCons/RecNil value structure necessary. My first attempt is > below. "def" is defined as "Query (Rel r)": > > unRel :: (Rel r) -> r > unRel r = undefined > > tableColumns :: ModelTable -> [String] > tableColumns (ModelTable _ _ _ def _) = recordLabels . unRel . snd . > runQueryRel $ def > > The types work out but the undefined in unRel causes a runtime error. > Looking at the instances for ShowLabels, I found the culprit: > > instance (FieldTag f,ShowLabels r) => ShowLabels (RecCons f a r) where > recordLabels x@(RecCons _ r) = consFieldName x : recordLabels r > > Even though consFieldName never looks at its argument, the pattern > match causes the failure. I modified the ShowLabels instance so it > makes a lazy pattern match: > > instance (FieldTag f,ShowLabels r) => ShowLabels (RecCons f a r) where > recordLabels ~x@(RecCons _ r) = consFieldName x : recordLabels r > > And lo and behold, it works! Now - is that advisable? Can anyone see a > problem with other portions of the system? There are several other > instances in HDBRec.hs where it looks like lazy matches should be > made. What's nice is, if the RecCons values really are needed, they > are still available to those that supplied them. > > I'll submit a patch if it seems like a reasonable change. I think that this is reasonable. Any place that does pattern matching just to recover the types of some constructor arguments should use lazy pattern matching (aka irrefutable patterns). Consider the current code buggy. /Björn |