Using unsafePerformIO safely?

Unless the “intermediate state” can be multiplexed and referenced, then you can represent it in a safe API as an opaque value, to be passed around like a pure value.

This is similar to the following musing: Most Haskell Web frameworks like to use (some amount of) purity in theirs “Views”: The monadic controller code, with full access to the database, generates a pure value with all information needed and passes that to a pure function that turns it into HTML (applying templates etc.) This is very pretty, as it guarantees that the view doesn’t update account balances or shenanigans like that.

But I wonder what’s so bad if the view code could read more data from the database? Why does the controller need to know if the view might choose to print “5 comments” next to a post?

Now, even read-only access to the database wouldn’t be pure, due to concurrent writes…

But what if the data base connection passed to the view could point to a immutable snapshop of the database (assuming such a things is possible – is it?), and the view has access to a pure (unsafePerformIO-wrapped) API to fetch more data? It seems that then we could allow the code in the view component to freely load more data as necessary – just as we would if all data would be in-memory anyways.

Has this been done before?