nodeFromList k xs       = build k 0 xs
    where
        at v i | V.length v < k = error "fromList: Vector too short"
               | otherwise      = v ! i
        build k depth xs =
            let axis = depth `mod` k
                xs' = List.sortBy (comparing (flip (!) axis . fst)) xs
                median = length xs' `div` 2
            in Node axis (fst (xs' !! median) `at` axis)
                    (nodeFromList k (take median xs'))
                    (nodeFromList k (drop median xs'))

-- fromList [] = Empty
-- fromList [(v, a)] = Leaf v [a]
-- fromList xs =
--     let
--         dims = transposeV (map fst xs)
--         meanVars = filter (\(_, (_, v)) -> v > 0) (zip [0..] (map meanVariance dims))
--     in
--         if null meanVars
--         then Leaf (fst (head xs)) (map snd xs)
--         else let (minVarDim, (minMean, _)) = List.minimumBy (comparing (snd.snd)) meanVars
--                  (left, right) = List.partition (\(v, _) -> v ! minVarDim < minMean) xs
--              in Node minVarDim minMean (fromList (traceShow left left)) (fromList right)
nodeFromList k xs       = build k 0 xs
    where
        at v i | V.length v < k = error "fromList: Vector too short"
               | otherwise      = v ! i
        build k depth xs =
            let axis = depth `mod` k
                xs' = List.sortBy (comparing (flip (!) axis . fst)) xs
                median = length xs' `div` 2
            in Node axis (fst (xs' !! median) `at` axis)
                    (nodeFromList k (take median xs'))
                    (nodeFromList k (drop median xs'))

-- fromList [] = Empty
-- fromList [(v, a)] = Leaf v [a]
-- fromList xs =
--     let
--         dims = transposeV (map fst xs)
--         meanVars = filter (\(_, (_, v)) -> v > 0) (zip [0..] (map meanVariance dims))
--     in
--         if null meanVars
--         then Leaf (fst (head xs)) (map snd xs)
--         else let (minVarDim, (minMean, _)) = List.minimumBy (comparing (snd.snd)) meanVars
--                  (left, right) = List.partition (\(v, _) -> v ! minVarDim < minMean) xs
--              in Node minVarDim minMean (fromList (traceShow left left)) (fromList right)
nodeFromList k xs       = build k 0 xs
    where
        at v i | V.length v < k = error "fromList: Vector too short"
               | otherwise      = v ! i
        build k depth xs =
            let axis = depth `mod` k
                xs' = List.sortBy (comparing (flip (!) axis . fst)) xs
                median = length xs' `div` 2
            in Node axis (fst (xs' !! median) `at` axis)
                    (nodeFromList k (take median xs'))
                    (nodeFromList k (drop median xs'))

-- fromList [] = Empty
-- fromList [(v, a)] = Leaf v [a]
-- fromList xs =
--     let
--         dims = transposeV (map fst xs)
--         meanVars = filter (\(_, (_, v)) -> v > 0) (zip [0..] (map meanVariance dims))
--     in
--         if null meanVars
--         then Leaf (fst (head xs)) (map snd xs)
--         else let (minVarDim, (minMean, _)) = List.minimumBy (comparing (snd.snd)) meanVars
--                  (left, right) = List.partition (\(v, _) -> v ! minVarDim < minMean) xs
--              in Node minVarDim minMean (fromList (traceShow left left)) (fromList right)