I am experimenting with STM by implementing the dining philsophers problems.
Anyway, I have the following definitions.
data ChopStick = CS (TVar Bool)
takeChopstick :: ChopStick -> STM ()
takeChopstick (CS chopstick) = do
    isTaken <- readTVar chopstick
    check (isTaken)
    writeTVar chopstick True
This function is called atomically:
atomically $ do
    takeChopstick leftChopstick
    takeChopstick rightChopstick
When running the program with the above definition of takeChopstick, I experience different results to running it with this definition:
takeChopstick :: ChopStick -> STM ()
takeChopstick (CS chopstick) = do
    isTaken <- readTVar chopstick
    if isTaken
        then retry
        else writeTVar chopstick True
In particular, the program hangs.
The source code for check (hackage, stm-2.2.0.1) is as follows:
check :: Bool -> STM a
check b = if b then return undefined else retry
Which appears to be effectively the same as my explicit use of retry.
How does check differ to explicitly using retry? Is pushing the retry call further down causing it to restart a different atomic block? 
                        
No,
checkis no different than to usingretryexplicitly, I simply confused the argument tocheck.The solution is to
checkthatisTakenisFalse, i.e.,check $ not isTaken.