Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
topSort :: V.Vector ([Int], [Int])
-> Either String [Int]
topSort kob =
let
sup u k = do
let max i = (i,) . head . snd <$> k `MV.read` i
l <- mapM max u
case filter (uncurry (==)) l of
[(a,_)] -> return $ Right a
x -> return $ Left "Topology error"
rewrite k s (i, j) = do
let f x | x == s && j < 0 = []
| x == s = [j]
| otherwise = [x]
when (j>=0) $ MV.modify k (_1 %~ (i:)) j
MV.modify k (_2 %~ (>>= f)) i
go u k =
readSTRef u >>= \case
[a] -> return $ Right [a]
u_ -> sup u_ k >>= \case
Right s -> do
modifySTRef' u $ Data.List.delete s
s_d <- fst <$> MV.read k s
mapM_ (rewrite k s) $ zip s_d (tail s_d ++ [-1])
tail <- go u k
return $ (s:) <$> tail
Left err ->
return $ Left err
in runST $ do
u <- newSTRef $ [0..V.length kob-1]
k <- V.thaw kob
liftM reverse <$> go u k
Если бы не название функции, я бы не догадался, что тут происходит. Где ты это откопал?
Я так понимаю, u — это список(sic!) ещё не посещённых вершин. Не понятно только, зачем нужен медленный список внутри мутабельной переменной, когда гораздо проще использовать мутабельный массив, как это делается в Data.Graph?
> Either String
тоже забавно, stringly typed programming
> Где ты это откопал?
Сам высрал как прототип. Во время бессонницы, скажу в оправдание.
> Не понятно только, зачем нужен медленный список внутри мутабельной переменной, когда гораздо проще использовать мутабельный массив, как это делается в Data.Graph?
В основном потому что этот код мутировал из иммутабельного.
> import Data.Graph (topSort)
Это не просто граф, т.к. входные данные несут не только инвормацию о рёбрах, но ещё и об относительном порядке в результирующем массиве. Обычный топсорт её проебёт.
У меня роль играет, в каком именно порядке рёбра определены в _каждой_ вершине, так что это не просто некий граф, а более информативная кобенация, которую можно было бы представить и обычным графом, но гораздо большего размера.
Я так понимаю, u — это список(sic!) ещё не посещённых вершин. Не понятно только, зачем нужен медленный список внутри мутабельной переменной, когда гораздо проще использовать мутабельный массив, как это делается в Data.Graph?
> Either String
тоже забавно, stringly typed programming
Ну и import Data.Graph (topSort), разумеется.
Сам высрал как прототип. Во время бессонницы, скажу в оправдание.
> Не понятно только, зачем нужен медленный список внутри мутабельной переменной, когда гораздо проще использовать мутабельный массив, как это делается в Data.Graph?
В основном потому что этот код мутировал из иммутабельного.
> import Data.Graph (topSort)
Это не просто граф, т.к. входные данные несут не только инвормацию о рёбрах, но ещё и об относительном порядке в результирующем массиве. Обычный топсорт её проебёт.
Используй алгоритм Kahn-а вместо dfs, он может выдавать лексикографически-минимальную топологическую сортировку.
Как видишь, для эффективности нужно иметь ещё и инвертированный граф, чтобы быстро находить рёбра, входящие в вершину ("incoming_edges(G, v)").