如何在命令行ghci中对Haskell中的列表进行排序

时间:2013-09-29 20:31:26

标签: list sorting haskell

我是Haskell的新手,我想创建一个将两个列表合并在一起的函数,然后将组合列表从最小到最大排序。 这应该在命令行中完成而不使用模块。

这是我目前所拥有的,我无法使“sortList”功能起作用,而且我也不知道如何将这3行合并为1个功能。

let combineList xs ys = xs++ys
let zs = combineList xs ys
let sortList (z:zs) = if (head zs) < z then (zs:z) else (z:(sortList zs))

2 个答案:

答案 0 :(得分:18)

如何在ghci中对列表进行排序:

Prelude> :m + Data.List
Prelude Data.List> sort [1,4,2,0]
[0,1,2,4]

关于您的职能

let combineList xs ys = xs++ys

为append函数创建另一个别名有什么意义?但如果你真的想要一个 - 它可以定义为let combineList = (++)

let zs = combineList xs ys

没有任何意义,因为xsyscombineList之外是未知的。

let sortList (z:zs) = if (head zs) < z then (zs:z) else (z:(sort zs))

此定义无效,因为它不包括空列表情况,(zs:z)生成无限类型,sort尚未定义。您可以通过另一种模式匹配获得head zs then。也许你不想在if声明的{{1}}部分进行另一次递归调用。最后我应该承认这种排序算法根本不起作用。

答案 1 :(得分:4)

在ghci中定义排序函数有点尴尬。我最简单的方法是在文件中编写排序函数,然后将其加载到ghci中。例如,您可以在名为sort.hs的文件(取自the HaskellWiki)中编写这个简洁(虽然不是就地!)版本的快速排序:

quicksort :: Ord a => [a] -> [a]
quicksort []     = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
    where
        lesser  = filter (< p) xs
        greater = filter (>= p) xs

并将其加载到ghci:

> :l sort.hs 

如果你真的想在ghci中定义函数,你可以这样做(来自the Haskell user's guide):

> :{
> let { quicksort [] = []
>     ; quicksort (p:xs) = (quicksort (filter (< p) xs)) ++ [p] ++ (quicksort (filter (>= p) xs))
>     }
> :}

一旦定义了这个,你就可以

> let combineAndSort xs ys = quicksort (xs ++ ys)

正如另一个答案已经解释过的那样,从Data.List导入排序当然会更快,但手动完成这绝对是一个很好的练习。

您的问题表明您对Haskell中的变量范围有点困惑。在这一行

> let combineList xs ys = xs++ys

您引入变量xsys。在等号的左侧提及它们只意味着combineList接受两个变量,并且在该函数的主体中,您将这些变量称为xsys。它不会在函数之外引入名称,所以下一行

> let zs = combineList xs ys

没有意义,因为名称xsys仅在combineList范围内有效。要使zs具有值,您需要给combineList一些具体的参数,例如:

> let zs = combineList [2,4,6] [1,3,5]  --> [2,4,6,1,3,5]

但是由于combineList的主体是如此简单,实际上更容易做到:

> let zs = [2,4,6] ++ [1,3,5] --> [2,4,6,1,3,5]

最后一行是

> let sortList (z:zs) = if (head zs) < z then (zs:z) else (z:(sortList zs))

我认为这条线让你很困惑,因为这里有很多不同的错误。 ДМИТРИЙМАЛИКОВ的回答提到了大部分内容,我建议您尝试理解他提到的每个错误。