IIUC, you can’t. The thing with concrete type annotations is that you get exactly this tradeoff: the compiler gets to know the type and can assume that it won’t change midway, so it get’s to generate code without runtime type checks. If your goal is precisely to change the function and thus the type of your field, then the compiler can not assume that it stays fixed and basically has to resolve everything at runtime, aka no optimization possible.
Possible solutions that I see:
- If your cost functions share a common structure and only differ in some of the parameters that are used, you can switch to storing the parameters that determine the cost function instead and have the calculation itself fixed.
- If that’s not possible, you can try to contain the instability in your code as much as possible. Basically try to separate the fast bits from the instable part and annotate the resulting type of the cost function call if you can. This should ensure that everything that can be stable stays so. Still not good if you want to call the cost function in a hot loop I guess.
- If so, the only good solution that I can come up with is to basically propagate the function type so far up that everything that need to be in a hot loop is aware of the function type at any moment and updating the cost function would then have to happen outside of this scope. This should then compile a fast version of the code for every concrete cost function, but you obviously pay i compile time for that. You kinda have to decide/try what works best for you, or somebody else comes up with a clever solution. Good luck anyways