Prostě bavili jsme se o tom, že v rámci STM se neděje* žádná tajemná nečistá inplace magie.
No ten STRef je v implementaci fakt normální mutable proměnná, akorát že ukazuje na thunk, čili může obsahovat výpočet. Jestli je schopne to při dostatečné striktnosti kompiler nějak vyoptimalizovat pryč, to netuším.
Pokud bylo v proměnné x, tak (modifySTRef ref f) vytváří akci, která do ní zapisuje f(x). Proto když se to udělá mockrát za sebou, tak mi tam ten stack narůstá. Viz zdroják:
modifySTRef ref f = writeSTRef ref . f =<< readSTRef ref
Oproti tomu čárkovaná verze udělá to, že vytvoří akci, která zapíše přímo hodnotu f(x):
modifySTRef' ref f = do
x <- readSTRef ref
let x' = f x
x' `seq` writeSTRef ref x'
Že se tam neděje žádná nečistá magie myslím v tom smyslu, že je to stejně čisté jako IO - pořád se prostě operuje jenom se statickými akcemi, které jdou spustit jenom mimo jazyk samotný, stejně jako IO.