-- given a start position construct shortest paths to all other positions
dijkstra :: Graph -> Distance -> Vertex -> Dijkstra
dijkstra graph dist start = buildDijkstra $ unfoldr (step graph dist) $ relax (start, Priority 0 start) queue
  where
    queue = PSQ.fromList $ map (\v -> v :-> Priority maxBound start) (S.toList $ vertices graph start)
    buildDijkstra = foldl' insertEdge (Dijkstra M.empty)
    insertEdge dij@(Dijkstra p) (destination, _, source) = if source /= destination then Dijkstra (M.insert destination source p) else dij

-- construct next edge in the graph taking the vertex with minimal cost
dijkstra :: Graph -> Distance -> Vertex -> Dijkstra
dijkstra graph dist start = buildDijkstra $ unfoldr (step graph dist) $ relax (start, Priority 0 start) queue
  where
    queue = PSQ.fromList $ map (\v -> v :-> Priority maxBound start) (S.toList $ vertices graph start)
    buildDijkstra = foldl' insertEdge (Dijkstra M.empty)
    insertEdge dij@(Dijkstra p) (destination, _, source) = if source /= destination then Dijkstra (M.insert destination source p) else dij

-- construct next edge in the graph taking the vertex with minimal cost
dijkstra graph dist start = buildDijkstra $ unfoldr (step graph dist) $ relax (start, Priority 0 start) queue
  where
    queue = PSQ.fromList $ map (\v -> v :-> Priority maxBound start) (S.toList $ vertices graph start)
    buildDijkstra = foldl' insertEdge (Dijkstra M.empty)
    insertEdge dij@(Dijkstra p) (destination, _, source) = if source /= destination then Dijkstra (M.insert destination source p) else dij

-- construct next edge in the graph taking the vertex with minimal cost