In this recipe, we will use ST s a, which is defined as follows:
newtype ST s a = GHC.ST.ST (GHC.ST.STRep s a)
The ST is a special monad that lets us update in place. But it allows us to do this without explicit IO, by allowing us to escape ST. This is done by using runST. The function runST has a peculiar type:
runST :: (forall s. ST s a) -> a
This is a rank 2 type, as the function runST must take an argument of type ST s and this argument should be universal in terms of s. Also note that the quantification (forall s . ST s a) helps runST escape ST.
In fact, all functions of rank 1, such as map can be used with quantifiers for example
map :: forall a b . (a -> b) -> [a] -> [b]
However, with runST, by specifying (forall ...