Вы забыли скобки в своих рекурсивных msort
вызовах:
msort :: [Int] -> [Int]
msort xs
| length xs <= 1 = xs
| otherwise = merge (msort <b>(</b>fst (halve xs)<b>)</b>) (msort <b>(</b>snd (halve xs)<b>)</b>)
Как говорится, использование length
часто не хорошая идея, так как оно работает в О (п) . Здесь лучше использовать сопоставление с образцом. Кроме того, вы можете использовать предложение where
, чтобы избежать вычисления halve xs
дважды:
msort :: Ord a => [a] -> [a]
msort [] = []
msort [x] = [x]
msort xs = merge (msort la) (msort lb)
where (la, lb) = halve xs
halve
может быть создан, когда мы передаем каждый второй элемент одному из элементов 2-кортежа, например:
halve :: [a] -> ([a], [a])
halve [] = ([], [])
halve (x:xs) = (x:ya, yb)
where (yb, ya) = halve xs
или с шаблоном foldr
:
halve :: [a] -> ([a], [a])
halve = foldr (\x (yb, ya) -> (x:ya, yb)) ([], [])
и merge
могут быть реализованы более элегантно с использованием as-pattern :
merge :: Ord a => [a] -> [a] -> [a]
merge [] ys = ys
merge xs [] = xs
merge <b>xa@</b>(x:xs) <b>ya@</b>(y:ys)
| x <= y = x : merge xs ya
| otherwise = y : merge xa ys