RunST prevents link access of another state stream in close

I came across many explanations like RunST Rank 2 and how it prevents link references from RunST. But I could not understand why this also prevents the following type checking code (which is correct, but I still want to understand how this is done):

test = do v ← newSTRef True let a = runST $ readSTRef v return True 

Compared with:

 test = do v ← newSTRef True let a = runST $ newSTRef True >>= λv → readSTRef v return True 

It seems to me that the type of newSTRef same for both cases: Λs. Bool → ST s (STRef s Bool) Λs. Bool → ST s (STRef s Bool) . And type v is equal to ∃s. STRef s Bool ∃s. STRef s Bool in both cases, if I understand correctly. But then I am puzzled by what to do next, to show why the first example does not print the check, I do not see the difference between the two examples, except that in the first example v attached to runST and inside inside secondly, I suspect that this is the key. Please help me show this and / or correct me if I am mistaken somewhere according to my reasoning.

+8
types haskell monads
source share
1 answer

The function runST :: (forall s . ST sa) -> a is where magic happens. The right question to ask is what it takes to perform a calculation with type forall s . ST sa forall s . ST sa .

Reading it as English, this is a calculation that is valid for all variants of s , a phantom variable that indicates the specific "stream" of the ST calculation.

When you use newSTRef :: a -> ST s (STRef sa) , you create a STRef that shares its stream variable with the ST stream that generates it. This means that the type s for the value of v fixed as identical to the type s for the larger thread. This fixation means that operations with v no longer valid for all the "variants" of s . Thus, runST reject operations with v .

Conversely, a calculation like newSTRef True >>= \v -> readSTRef v makes sense in any ST stream. All computation is of a type that is valid for all ST threads s . This means that it can be started using runST .

Typically, runST should wrap the creation of all ST threads. This means that all variants of s inside the runST argument runST arbitrary. If something from the context surrounding runST interacts with the runST argument, then this will most likely correct some of these s options to suit the surrounding context and, therefore, will no longer be freely applied to all s options.

+13
source share

All Articles