The problem here...
module Keys : sig
val recovery : int Univ_map.Key.t
val resist_pain : float Univ_map.Key.t
...
Would be that Keys would now have dependence on types spanning the codebase.
Say these modifiers use Wounds.t, Fatigue.t, Ability.Score.t, ... There are a
lot of types, which mostly have a limited scope (their own module and a few
others). Wouldn't it be a problem to have all types brought into this one
module, which every other module also becomes dependent on? Maybe it just
feels like a problem but it's just an aesthetic -- Would you do this? A few
hundred keys involving types from half the modules of the codebase?
I'm trying to use these "modifiers" for code organisation -- declaring
snippets of functionality (all of signature 'a -> 'a... to return modified
input) in a lightweight manner, which can be applied elsewhere.
For example, the Virtue module can add a lot of modifers to an entity (UID).
Say one entity has virtues of Agility, Inspirational, and Sun-cyclic Magic,
which each adding a few modifier functions keyed to various contexts
(sun-cyclic magic: "Casting" is +3 while the sun is up). The associated
modifiers would be picked up in code spread throughout the application. Rules
for combat, spellcasting, even character dialog...
Rather than having character dialog checking for "does he have this virtue, or
that one? How about this ability? Spell-effects? Reputations? ..." I want to
apply all appropriate/active modifiers for entity and situation which come
from other rules. So, dialog code might have a current_value, then...
eg.
let modified_value = apply_modifiers_for_context entity `CharmRoll current_value
There is a lot of work on my project which I've been avoiding because the
direct approach is building hairy nests of checks which call out to code
everywhere... effectively splitting logic between the point of origin of a
rule, and the point of application of it. I'd rather declare the individual
rules, each in one piece, and "magically" apply the aggregate of rules.
In a way, what I'm looking for is having a grand-central lookup, which
*trusts* that I'm using the right keys at the right time (where the keys are
purely symbolic with no type info)... but it would be nice if once the whole
program is compiled it could identify whether that trust was broken afterall.
A bit of a pipe-dream, and maybe even flawed logic. :)
It might sound like I'm being too picky or even whiney... that declaring keys
throughout the code is unacceptable, or having a file dependent on all types
is problematic... maybe I am? The first seems disorganised and adds a
mental burden to deciding and knowing where keys live; the second is a
problem, isn't it?
Dynamic languages can do what I want at the cost of typesafety. So I might
just prefer to make that same tradeoff for one mechanism in my code... "famous
last words"? I hope not. I hope it just works and I don't have nightmares
about lurking segfaults. :)