
versionSort :: [String] -> [String] versionSort = sortOn brkND where tr f g (x,y) = f x : g y -- ND for non-digits brkND = tr Right brkD . span (not . isDigit) brkD = tr (Left . read @Int) brkND . span isDigit
(side question: does the helper function tr I defined above have a commonly known name?)
I don't think so, but that's just because you made the cut at a weird point. It's very close to (***) https://hoogle.haskell.org/?hoogle=%28***%29&scope=set%3Astackage from Control.Arrow, Data.Tuple.Extra, Data.Profunctor, and other libraries, also known as bimap https://hoogle.haskell.org/?hoogle=bimap&scope=set%3Astackage in Data.Bifunctor and in the lens package. Rewriting your functions to tease it out even more (not tested): versionSort :: [String] -> [String] versionSort = sortOn gatherNonDigits where gatherAll predicate gather continue = uncurry (:) . (gather *** continue) . span predicate -- 'NonDigits' for non-digits gatherNonDigits = gatherAll (not . isDigit) wrapNonDigits gatherDigits gatherDigits = gatherAll isDigit wrapDigits gatherNonDigits wrapNonDigits = Right wrapDigits = Left . read @Int