Suppose I have a function of type unionWith# :: (Hashable k, Eq k) => (a -> a -> (# a #)) -> HashMap k a -> HashMap k a -> HashMap k a
I can use this to implement strict and lazy unions with practically no code duplication either in source or in generated code: S.unionWith, L.unionWith :: (Hashable k, Eq k) => (a -> a -> a) -> HashMap k a -> HashMap k a -> HashMap k S.unionWith f = unionWith# (\a b -> let !r = f a b in (# r #)) L.unionWith f = unionWith# (\a b -> (# f a b #)) Semantically, this gets the job done, but there's a potential performance problem. If the function passed to either version of unionWith fails to inline, then we'll build a closure to interface with the underlying function. This is not so great, because it adds indirection in a likely hot spot. I'm not too terribly worried about the lazy version, because it's prone to leaking memory anyway, but I do care about the strict version. It seems to me that for the *strict* version, I can probably use unsafeCoerce to do the job instead: S.unionWith f = unionWith# (unsafeCoerce f) When unionWith# applies f to values, it will get back something that it *thinks* might be a thunk, but actually will never be a thunk. We don't really care, especially because we just stick it into a lazy constructor field. My main concern is that this is obviously not at all an officially supported way to use unsafeCoerce. What are the chances that GHC will do something that breaks it? If I can't do this reliably, I should still be able to use unionWith# to reduce *source* size, relying on lots of inlining to avoid closures, but the generated code would stay large. David _______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users