如何在 Idris 中编写一个简单的基于列表的快速排序?

How to write a simple list-based quicksort in Idris?

我只是想尽最大努力将以下 Haskell 翻译成 Idris(我不是在寻找效率或正确性证明):

quicksort  []           =  []
quicksort (x:xs)        =  quicksort [y | y <- xs, y<x ]
                        ++ [x]
                        ++ quicksort [y | y <- xs, y>=x]

这是我的 Idris 代码,除了需要告诉 Idris 我们正在处理有序类型外,它与 Haskell 基本没有变化:

quicksort: List (Ord b) -> List (Ord b)
quicksort  []           =  []
quicksort (x::xs)       =  quicksort [y | y <- xs, y<x ]
                        ++ [x]
                        ++ quicksort [y | y <- xs, y>=x]

但是,我显然做错了。我在 看到问题有答案,但形式有点不同 - 我想了解当前方法有什么问题。我上面的代码给出了错误:

40 | quicksort (x::xs)       =  quicksort [y | y <- xs, y<x ]
   |                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...
When checking right hand side of quicksort with expected type
        List b

When checking an application of function Prelude.Applicative.guard:
        Can't find implementation for Ord (Ord b)

问题是 Prelude.Applicative.guard(用于列表推导中的守卫的函数)找不到 Ord 类型类的实现。

这告诉我们,我们没有添加(或错误添加)类型类约束。如果我们将您的代码更改为这个,它应该可以工作:

quicksort: Ord b => List b -> List  b
quicksort  []           =  []
quicksort (x::xs)       =  quicksort [y | y <- xs, y < x ]
                        ++ [x]
                        ++ quicksort [y | y <- xs, y >= x]

澄清一下:List (Ord b)Ord b 的实现列表,而 Ord b => List bb 的列表,其中 b 具有接口约束Ord b 个。比较:

[ord1] Ord Nat where
   compare Z (S n)     = GT
   compare (S n) Z     = LT
   compare Z Z         = EQ
   compare (S x) (S y) = compare @{ord1} x y

imps : List (Ord b) -> List (Ord b)
imps xs = xs

ords : Ord b => List b -> List b
ords xs = xs

imps [ord1] : List (Ord Nat)ords [1] : List Nat