带有两个合并函数asc和desc的Haskell合并排序
我想使用合并排序算法。mergeSort是等待合并函数作为第一个参数的主函数。有人知道我的问题在哪里吗?事先非常感谢带有两个合并函数asc和desc的Haskell合并排序,haskell,mergesort,Haskell,Mergesort,我想使用合并排序算法。mergeSort是等待合并函数作为第一个参数的主函数。有人知道我的问题在哪里吗?事先非常感谢 mergeSort xs = merge xs mergeDesc xs = reverse (mergeAsc xs) mergeAsc [] = [] mergeAsc [x] = [x] mergeAsc xs = merge (mergeAsc top) (mergeAsc bottom) where (top, bottom) = splitAt (length xs
mergeSort xs = merge xs
mergeDesc xs = reverse (mergeAsc xs)
mergeAsc [] = []
mergeAsc [x] = [x]
mergeAsc xs = merge (mergeAsc top) (mergeAsc bottom) where (top, bottom) = splitAt (length xs `div` 2) xs
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) | x <= y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys
将类型签名添加到函数中,问题就会变得很明显:
mergeAsc, mergeDesc :: Ord a => [a] -> [a]
mergeDesc xs = reverse (mergeAsc xs)
mergeAsc [] = []
mergeAsc [x] = [x]
mergeAsc xs = merge (mergeAsc top) (mergeAsc bottom) where (top, bottom) = splitAt (length xs `div` 2) xs
merge :: Ord a => [a] -> [a] -> [a]
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) | x <= y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys
或者更简单更喜欢
mergeSort = margeAsc
请注意,mergeDesc并不是很好:您首先按错误的顺序对列表排序,然后将其反转?在Haskell中,您希望您的算法足够灵活,能够自行处理不同的排序之类的内容。所以你会定义
mergeSortBy :: (a->a->Ordering) -> [a] -> [a]
mergeSortBy cmp = mSort
where
mSort [] = []
mSort [x] = [x]
mSort xs = merge (mSort top) (mSort bottom)
where (top, bottom) = splitAt (length xs `quot` 2) xs
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = case x`cmp`y of
LT -> x : merge xs (y:ys)
_ -> y : merge (x:xs) ys
然后,您可以简单地定义mergeSort=mergeSortBy compare和mergeSortDesc=mergeSortBy flip compare
还要观察将merge设置为本地函数如何防止实现中的错误
它说它应该声明为:mergeSort::[a]->[a]->[a]->[a]->[a]->[a]作为接受合并函数作为第一个参数的函数
这很奇怪,它不应该被称为mergeSort,而是sortWithMerge之类的。无论如何,这样做很简单:只需抛出仅在merge子函数中使用的cmp!并将其替换为merge作为参数,而不是在本地定义它
sortWithMerge :: ([a]->[a]->[a]) -> [a] -> [a]
sortWithMerge merger = mSort
where
mSort [] = []
mSort [x] = [x]
mSort xs = merger (mSort top) (mSort bottom)
where (top, bottom) = splitAt (length xs `quot` 2) xs
将类型签名添加到函数中,问题就会变得很明显:
mergeAsc, mergeDesc :: Ord a => [a] -> [a]
mergeDesc xs = reverse (mergeAsc xs)
mergeAsc [] = []
mergeAsc [x] = [x]
mergeAsc xs = merge (mergeAsc top) (mergeAsc bottom) where (top, bottom) = splitAt (length xs `div` 2) xs
merge :: Ord a => [a] -> [a] -> [a]
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) | x <= y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys
或者更简单更喜欢
mergeSort = margeAsc
请注意,mergeDesc并不是很好:您首先按错误的顺序对列表排序,然后将其反转?在Haskell中,您希望您的算法足够灵活,能够自行处理不同的排序之类的内容。所以你会定义
mergeSortBy :: (a->a->Ordering) -> [a] -> [a]
mergeSortBy cmp = mSort
where
mSort [] = []
mSort [x] = [x]
mSort xs = merge (mSort top) (mSort bottom)
where (top, bottom) = splitAt (length xs `quot` 2) xs
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = case x`cmp`y of
LT -> x : merge xs (y:ys)
_ -> y : merge (x:xs) ys
然后,您可以简单地定义mergeSort=mergeSortBy compare和mergeSortDesc=mergeSortBy flip compare
还要观察将merge设置为本地函数如何防止实现中的错误
它说它应该声明为:mergeSort::[a]->[a]->[a]->[a]->[a]->[a]作为接受合并函数作为第一个参数的函数
这很奇怪,它不应该被称为mergeSort,而是sortWithMerge之类的。无论如何,这样做很简单:只需抛出仅在merge子函数中使用的cmp!并将其替换为merge作为参数,而不是在本地定义它
sortWithMerge :: ([a]->[a]->[a]) -> [a] -> [a]
sortWithMerge merger = mSort
where
mSort [] = []
mSort [x] = [x]
mSort xs = merger (mSort top) (mSort bottom)
where (top, bottom) = splitAt (length xs `quot` 2) xs
非常感谢您,我需要知道的最后一件事是,当我将mergeSort函数的类型签名设置为:mergeSort::[a]->[a]->[a]->[a]->[a]->[a]时,应用程序中出现了类型错误。。。如何解决这个问题?这两个类型声明必须是您和我定义它的方式。到目前为止,谢谢@leftaroundabout:为什么您认为它应该是[a]->[a]->[a]->[a]->[a]->[a]?因为我有一个特定的任务要完成,它说它应该声明为:mergeSort::[a]->[a]->[a]->[a]->[a]->[a]作为接受合并函数作为第一个参数的函数。。。还有两个单独的合并函数,它们对值进行升序和降序排序,如我的解决方案所示,这两个函数应该声明为:Ord a=>[a]->[a]任务说明:编写一个mergeSort合并排序函数,它等待合并函数作为第一个参数。mergeSort::[a]->[a]->[a]->[a]->[a]->[a]写两个额外的合并函数,它们将对值进行升序/降序mergeDesc::Ord a=>[a]->[a]->[a]mergeAsc::Ord a=>[a]->[a]->[a]@baron ok。。。虽然正如我所说,这不应该被称为合并排序。至于mergeAsc和mergeDesc,我会再次将它们作为普通mergeGen::a->a->Ordering->[a]->[a]->[a]->[a]的专业化实现,作为mergeAsc=mergeGen compare和mergeDesc=mergeGen$flip compare。非常感谢,这是我需要知道的最后一件事,当我将mergeSort函数的类型签名设置为:mergeSort::[a]->[a]->[a]->[a]->[a]->[a]时,这是应用程序中的类型错误。。。如何解决这个问题?这两个类型声明必须是您和我定义它的方式。到目前为止,谢谢@leftaroundabout:为什么您认为它应该是[a]->[a]->[a]->[a]->[a]->[a]?因为我有一个特定的任务要完成,它说它应该声明为:mergeSort::[a]->[a]->[a]->[a]->[a]->[a]作为接受合并函数作为第一个参数的函数。。。还有两个单独的合并函数,它们对值进行升序和降序排序,如我的解决方案所示,这两个函数应该声明为:Ord a=>[a]->[a]任务说明:编写一个mergeSort合并排序函数,它等待合并函数作为第一个参数。mergeSort::[a]->[a]->[a]->[a]->[a]->[a]写两个额外的合并函数,它们将对值进行升序/降序mergeDesc::Ord a=>[a]->[a]->[a]mergeAsc::Ord a=>[a]->[a]->[a]@baron ok。。。虽然正如我所说,这不应该被称为合并排序。至于mergeAsc和mergeDesc,我将再次将它们作为通用mergeGen::a->a->Ordering->[a]->[a]->[a]->[a]的专门化来实现 s mergeAsc=mergeGen比较和mergeDesc=mergeGen$flip比较。