首先,您的sortEm
函数名称具有误导性,它不会对其参数列表进行排序,而是将其头部元素插入其尾部。碰巧的是,模块insert
中已经有一个函数将其第一个参数插入到第二个参数中,因此存在等效性Data.List
sortEm (x:xs) === Data.List.insert x xs
现在,如果您将一个项目插入到一个已经排序的列表中,插入一个项目只会让您返回一个排序列表。由于空列表已排序,这myList
就是您在 dave4420 的答案中得到的功能。那是一种“插入”排序,将列表的元素逐步插入到辅助列表中,最初为空。这就是你在 dave4420 答案中得到的第二个函数的作用:
insertionSort xs = foldr Data.List.insert [] xs
这确实“应用排序”,即仅插入“每个元素”一次。对于列表[a,b,c,...,z]
,它相当于
insert a (insert b (insert c (... (insert z []) ...)))
您在评论中可能的意思,即“仅一次”比较(并可能交换)两个相邻元素,称为冒泡排序。当然,在一般情况下,只通过列表一次不会对其进行排序:
bubbleOnce xs = foldr g [] xs where
g x [] = [x]
g x xs@(y:ys) | x>y = y:x:ys -- swap x and y in the output
| otherwise = x:xs -- keep x before y in the output
现在,bubbleOnce [4,2,6,1,8] ==> [1,4,2,6,8]
. 您期望的值 ,将由从左到右的相反方向[2,4,1,6,8]
应用折叠函数产生。但这在 Haskell 列表中就不那么自然了:g
bubbleOnce' [] = []
bubbleOnce' (x:xs) = let (z,h)=foldl g (x,id) xs in (h [z]) where
g (x,f) y | x>y = (x, f.(y:)) -- swap x and y in the output
| otherwise = (y, f.(x:)) -- keep x before y in the output
(编辑 :)使用直接递归查看jimmyt 的答案以获得等效但简单且漂亮的版本。它也比这里的fodlr
和foldl
版本更懒惰(不那么严格)。