First of all, it is a very good and fair question. You're right, you can achieve the same with mnesia + ram_copies + fragmentation, BUT performance won't ever be the same, mnesia is a heavy layer on top of ETS and DETS, if you want to write something, in case of fragmentation, you use transaction, and that takes time, and compared with ETS or Shards, latency is much much higher – even if you can use dirty_write is much higher. I did performance test some time ago, in order to compare this, and mesia_frag started to fail and crash pretty soon – probably after 3000-5000 ops/seg. I did some performances test with shards that you can check here: http://cabol.github.io/posts/2016/04/14/sharding-support-for... (BTW, I'll add mnesia_frag to that bench test). Besides I wrote some other test, which includes mnesia_frag here: https://github.com/cabol/shards_bench. Furthermore, you can do it out yourself using "https://github.com/basho/basho_bench" which is the tool that I've been using so far.
IMHO, they are similar libs/tools, which drives similar issues, but depending on the case, one tool can fits better to solve a set of problems than the other and viceverza. For example, the typical case, caching and/or distributed caching, here you want to be able not only to get the best performance, but also scale-out over the write-locks and contention, without compromise performance – as much as possible. In this case, ETS or Shards might be a better option. But suppose that you want to be able to handle RAM and Disk persistence transparently, you want to do it configurable, besides, be able to handle transaction, well, in that case, go for mnesia might be better option. But in general, if you always gonna have memory storage, might be better option go for ETS or in this case Shards, which add the ability to scale linearly over locks and contention issues.