I'm concerned with if and when a polymorphic "global" class value is shared/memoized, particularly across module boundaries. I have read this and this, but they don't quite seem to reflect my situation, and I'm seeing some different behavior from what one might expect from the answers.
Consider a class that exposes a value that can be expensive to compute:
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
module A
import Debug.Trace
class Costly a where
  costly :: a
instance Num i => Costly i where
  -- an expensive (but non-recursive) computation
  costly = trace "costly!" $ (repeat 1) !! 10000000
foo :: Int
foo = costly + 1
costlyInt :: Int
costlyInt = costly
And a separate module:
module B
import A
bar :: Int
bar = costly + 2
main = do
  print foo
  print bar
  print costlyInt
  print costlyInt
Running main yields two separate evaluations of costly (as indicated by the trace): one for foo, and one for bar.  I know that costlyInt just returns the (evaluated) costly from foo, because if I remove print foo from main then the first costlyInt becomes costly.  (I can also cause costlyInt to perform a separate evaluation no matter what, by generalizing the type of foo to Num a => a.)
I think I know why this behavior happens: the instance of Costly is effectively a function that takes a Num dictionary and generates a Costly dictionary.  So when compiling bar and resolving the reference to costly, ghc generates a fresh Costly dictionary, which has an expensive thunk in it.  Question 1: am I correct about this?
There are a few ways to cause just one evaluation of costly, including:
- Put everything in one module.
- Remove the Num iinstance constraint and just define aCostly Intinstance.
Unfortunately, the analogs of these solutions are not feasible in my program -- I have several modules that use the class value in its polymorphic form, and only in the top-level source file are concrete types finally used.
There are also changes that don't reduce the number of evaluations, such as:
- Using INLINE, INLINABLE, or NOINLINE on the costlydefinition in the instance. (I didn't expect this to work, but hey, worth a shot.)
- Using a SPECIALIZE instance Costly Intpragma in the instance definition.
The latter is surprising to me -- I'd expected it to be essentially equivalent to the second item above that did work.  That is, I thought it would generate a special Costly Int dictionary, which all of foo, bar, and costlyInt would share.  My question 2: what am I missing here? 
My final question: is there any relatively simple and foolproof way to get what I want, i.e., all references to costly of a particular concrete type being shared across modules?  From what I've seen so far, I suspect the answer is no, but I'm still holding out hope.
 
     
    