Отступы двух объявлений в предложении let
должны совпадать, например:
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let smallerSorted = quicksort [a | a <b><-</b> xs, a <= x]
biggerSorted = quicksort [a | a <b><-</b> xs, a > x] -- no extra spacing
in smallerSorted ++ [x] ++ biggerSorted
В исходном вопросе вы также забыли использовать оператор <-
в части выражения генератора вашего понимания списка: таким образом, вы должны написать a <- xs
вместо a xs
.
Однако, как говорит @ RobinZigmond , вы можете добавить пробелы до и после =
, если у вас есть одинаковое количество пробелов до первого непробельного символа, это нормально, как:
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let smallerSorted = quicksort [a | a <- xs, a <= x]
biggerSorted = quicksort [a | a <- xs, a > x] -- extra space before =
in smallerSorted ++ [x] ++ biggerSorted
Обратите внимание, что вы можете использовать partition :: (a -> Bool) -> [a] -> ([a], [a])
, чтобы разбить список на два списка, где первый подсписок имеет элементы, которые удовлетворяют предикату, а последний имеет элементы, которые делают не удовлетворяют предикату, например:
import Data.List(partition)
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let (smal, big) = partition (x >) xs
in quicksort smal ++ x : quicksort big
Функция partition
обычно реализуется таким образом, что она повторяется только один раз по заданному списку и выполняет проверку только один раз. Так что это обычно (немного) более эффективно, чем использование двух представлений списка, каждый из которых индивидуально фильтрует данный список.