Not that hard, but most don't care about uniform abilities/types. The usual randomizer iterates through all entries without any other context; just a simple foreach-loop behavior.
Different approaches that use other files as context can have various implementation issues, and need a well defined approach. Things get kinda hairy for alternate formes -- Gen7 introduced forme-specific evolutions, where a specific species-form has its own Evolution set. Also can be weird for future gen pre evolutions; which species of the evolution chain is the root? What about split evolutions like Eevee?
If a context based smart randomizer was desired, you'd probably want to determine the root for each species chain, then randomize the root (and all alt forms). For each root element that is modified, get the index within the PersonalTable (form stats index). With the index, get the evolution table entry. Propagate changes, and repeat the index-evolution recursion until the chain ends.
Won't really work well if the user randomizes evolutions after... The trickle up described above can be repeated at the end (types, moves), but stats and learnsets... yuck.
Basically, a smart randomizer has its own tradeoffs and users might want the ability to customize it further, which is a burden on the (mostly single person) implementer
If you want I can always discuss stuff on discord/irc