Evitando IORefs em código puro

eu percebi issoData.UnionFind usa a md IO para fornecer ponteiros via IORefs. Eu imagino que todo mundo chama alegrementeunsafePerformIO quando usá-lo localmente em código puro, uma vez que a estrutura de dados é tão bem compreendida, mas ..

Existe uma abordagem de limpeza canônica para essas estruturas de dados? Talvez um wrapper em torno de IO que faz o inevitávelunsafePerformIO menos inseguro "olhando", proibindo a maioria das operações de IO?