thunk :: ST s a -> ST s (ST s a) thunk action = do ref <- newSTRef Nothing return $ do cache <- readSTRef ref case cache of Just val -> return val Nothing -> do val <- action; writeSTRef ref (Just val); return val
tak :: STRef s Int -> ST s Int -> ST s Int -> ST s Int -> ST s Int tak counter ex ey ez = do modifySTRef counter (+1) x <- ex; y <- ey if x <= y then ey else do a <- thunk $ tak counter (pred <$> ex) ey ez b <- thunk $ tak counter (pred <$> ey) ez ex c <- thunk $ tak counter (pred <$> ez) ex ey tak counter a b c
takCount :: Int -> Int -> Int -> Int takCount x y z = runST (do counter <- newSTRef 0 _ <- tak counter (return x) (return y) (return z) readSTRef counter)