
Actually, I don't see anything wrong on the face of it with oncePerType :: Typeable a => IO a -> IO a since the only instances of Typeable are monomorphic. Indeed, the implementation seems pretty straightforward: store the results of already-run computations as Dynamic values in a global dictionary, keyed by TypeRep.
What happens if more than one 'once' function returns the same type? I guess you could wrap the types in a unique constructor. Infact you could use the HList library to produce a type indexed list with a unqiue type constraint that can be enforced at compile time. The version with the String key also seems interesting, as the key could be the name of the function being memoised, which has to be unique. Template-Haskell could be used to generate the reified string from the function name, it would end up like (in the new TH syntax): a <- $(once 'function) a b c Keean.