编译错误
如果我们查看来自 ghci 的整个错误消息,即:
* 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.
我们看到rest :: [a]。
但是你正试图在这里对rest 应用一些东西:
sort x = smallest x : sort (rest x)
但是你已经在这里申请了x:
rest = remove (smallest x) x
因此,只需将前者更改为:
sort x = smallest x : sort rest
它会编译。也就是说,我还没有检查算法本身的逻辑。
修复逻辑:
我用看起来更整洁的LambdaCase 扩展名重写了代码。
我还将您的排序功能重命名为 sort',这样它就不会与 Data.List (sort) 冲突。
sort' 中有 2 个问题。首先,您没有处理单例列表的情况,这导致了非详尽的模式匹配。我为此添加了子句[x] -> [x]。其次,您应该只使用let 绑定来评估smallest xs 一次,我也修复了这个问题。第三,您遇到了 Thomas M. DuBuisson 描述的问题,我已解决。下面是代码,有quickCheck 和所有。
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
运行快速检查:
> quickCheck prop_sort
+++ OK, passed 100 tests.
根据 Willem Van Onsem 提出的替代更改,smallest, sort 改为:
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也可以写成折叠:
import Data.List (foldl1)
smallest :: Ord a => [a] -> a
smallest = foldl1 $ \x y -> if x < y then x else y
也可以使用min :: Ord a => a -> a -> a,甚至更短:
import Data.List (foldl1)
smallest :: Ord a => [a] -> a
smallest = foldl1 min
因此我们的解决方案可以写成:
sort' :: Ord a => [a] -> [a]
sort' = \case [] -> [] ; xs -> let s = foldl1 min xs in s : sort' (remove s xs)