【发布时间】:2013-02-03 18:19:44
【问题描述】:
问题中的术语general(与specialized相反)意味着该函数可以对项目进行排序,只要它们属于@987654326实例的类型@.
考虑一下最著名的 Haskell 广告之一
quicksort :: Ord a => [a] -> [a]
quicksort [] = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
where
lesser = filter (< p) xs
greater = filter (>= p) xs
上面的实现没有到位。
我试图写一个就地版本。
就地进行快速排序很容易。通常,我们只需要一个可变数组,我选择了Foreign.Marshal.Array。
我的实现是就地的并且运行得很好,但是我对它的类型签名不满意
(Ord a, Storable a) => [a] -> IO [a]
更准确地说,类型约束Storable a 惹恼了我。
显然,如果我们要对项目进行排序,则需要 Ord 约束,而 Storable 是不必要的。
相比之下,经典快速排序或sort 中的Data.List 的类型签名是Ord a => [a] -> [a]。约束只是Ord。
我没有找到摆脱额外约束的方法。
我搜索了 Stackoverflow,发现了一些关于 Haskell 中就地快速排序的问题,例如
How do you do an in-place quicksort in Haskell
Why is the minimalist, example Haskell quicksort not a "true" quicksort?
不幸的是,他们的主要关注点就位。那里给出的所有就地快速排序示例也有额外的类型约束。
例如,iqsort given by klapaucius 具有类型签名
iqsort :: (Vector v a, Ord a) => v a -> v a
有人知道如何使用类型签名Ord a => [a] -> [a] 实现就地快速排序haskell 函数吗?
我知道如何进行就地快速排序,但我不知道如何使其通用。
【问题讨论】:
-
不是 Haskell 的意图(我的意思是 pure 函数式语言)针对就地类型的事情(因为就地修改是一种侧面-函数的效果,如果修改参数就不是纯函数)
-
就地和
Ord a => [a] -> [a]在一起没有意义。 Haskell 列表根本不会就地执行。您将需要使用 IO 或 ST 或 State 进行就地,因为就地意味着可变性。请注意,Vector v a的实例充满了易于拆箱的固定大小类型。 -
@VB9-UANIC 如果用户无法检测到突变,可以将突变隐藏在纯界面下。例如,请参阅
STmonad。 -
为什么是
Foreign?IOArray和STArray有什么问题? -
作为其他人谈论的示例,请参阅我在this previous answer 中的
vsort函数。