Compile Error
If we look at the entire error message from ghci, which is:
* Couldn't match expected type `[a] -> [a]' with actual type `[a]'
* The function `rest' is applied to one argument,
but its type `[a]' has none
In the first argument of `sort', namely `(rest x)'
In the second argument of `(:)', namely `sort (rest x)'
* Relevant bindings include
rest :: [a]
(bound at ...)
x :: [a]
(bound at ...)
sort :: [a] -> [a]
(bound at ...)
Failed, modules loaded: none.
We see that rest :: [a].
But you are attempting to apply something to rest here:
sort x = smallest x : sort (rest x)
But you had already applied x here:
rest = remove (smallest x) x
So, simply change the former to:
sort x = smallest x : sort rest
And it will compile. That said, I haven't checked the logic of the algorithm itself.
Fixing the logic:
I rewrote the code with the LambdaCase extension which looks neater.
I also renamed your sorting function to sort' so that it doesn't clash with Data.List (sort).
You had 2 problems in sort'. First, you didn't handle the case of a singleton list, which resulted in a non-exhaustive pattern match. I added the clause [x] -> [x] for this. Second, you should use a let binding to evaluate smallest xs only once, I fixed that too. Third, you had the problem that Thomas M. DuBuisson described, which I fixed. And below is the code, with quickCheck and all.
remove :: Eq a => a -> [a] -> [a]
remove a = \case
[] -> []
(x:xs) -> if a == x then xs else x : remove a xs
smallest :: Ord a => [a] -> a
smallest = \case
(x:y:[]) -> if x < y then x else y
(x:y:xs) -> if x < y then smallest (x:xs) else smallest (y:xs)
sort' :: Ord a => [a] -> [a]
sort' = \case
[ ] -> [ ]
[x] -> [x]
xs -> let s = smallest xs in s : sort' (remove s xs)
prop_sort :: Ord a => [a] -> Bool
prop_sort xs = sort xs == sort' xs
Running QuickCheck:
> quickCheck prop_sort
+++ OK, passed 100 tests.
With the alternate changes proposed by Willem Van Onsem, smallest, sort instead looks as:
smallest :: Ord a => [a] -> a
smallest = \case
[x] -> x
(x:y:xs) -> if x < y then smallest (x:xs) else smallest (y:xs)
sort' :: Ord a => [a] -> [a]
sort' = \case
[] -> []
xs -> let s = smallest xs in s : sort' (remove s xs)
smallest can also be written as a fold:
import Data.List (foldl1)
smallest :: Ord a => [a] -> a
smallest = foldl1 $ \x y -> if x < y then x else y
and even shorter with by also using min :: Ord a => a -> a -> a:
import Data.List (foldl1)
smallest :: Ord a => [a] -> a
smallest = foldl1 min
wherefore our solution can be written, in total as:
sort' :: Ord a => [a] -> [a]
sort' = \case [] -> [] ; xs -> let s = foldl1 min xs in s : sort' (remove s xs)
sort [1,1,1,1] == [1]. This is becauseremoveremoves all matching elements instead of just one.rest x, butrestis defined without any arguments.