Haskell:用于按字典顺序对3个元组的第一个元素进行排序

时间:2019-03-09 23:29:37

标签: haskell

假设我们有一个电子表格:: [(String,String,Int)]包含 三元组(名称,用户,标记),其中名称是学生,用户的姓氏 是他的用户名,标记是该学生的第一个CW的结果。 编写一个函数sortLastname以字典顺序对电子表格进行排序 使用练习2中定义的高阶插入排序按名称排序。

我的练习2代码:

homerge :: Ord b => (a -> b) -> [a] -> [a] -> [a]
homerge _ xs [] = xs
homerge _ [] ys = ys
homerge fun (x:xs) (y:ys) | fun x < fun y = x : homerge fun xs (y:ys)
                          | otherwise = y : homerge fun (x:xs) ys`


hoMergeSort :: Ord b => (a -> b) -> [a] -> [a]
hoMergeSort _ [x] = [x]
hoMergeSort fun xs = homerge fun (hoMergeSort fun ys) (hoMergeSort fun ws)
                 where (ys,ws) = (take l xs, drop l xs)
                               where l = length xs `div` 2

我当前的尝试:

sortLastName [(x,y,z)] = hoMergeSort ( (x,_,_) (x',_,_) = x<x' ) [(x,y,z)]

我的问题是获取正确的函数来检查3元组的第一个元素是否小于下一个元素。

任何建议将不胜感激。

2 个答案:

答案 0 :(得分:0)

让我们不运行。让我们慢慢移动:

-- sortLastName [(x,y,z)] = hoMergeSort ( (x,_,_) (x',_,_) = x<x' ) [(x,y,z)]
sortLastName xyzs = hoMergeSort fun xyzs
    where

让我们看一下这个定义,

-- homerge fun (x:xs) (y:ys) | fun x < fun y = x : homerge fun xs (y:ys)

看,我们在那里有fun xfun y?哪些结果作为操作数进入<比较中?

    fun (x,y,z) =  

我们要作为操作数进入<比较中的哪个值?

                  .....

fun不用于比较。 <在函数homerge的源代码中完成。 fun函数用于提供要在该比较中使用的值

慢慢走,走远。


请注意,这不是字典顺序。这与三元组的第n个字段排序,而与其他字段的值无关。词典顺序是

(x,y,z) < (a,b,c) = x < a || x==a && (y < b || y==b && z < c)

答案 1 :(得分:0)

语法

-- ( (x,_,_) (x',_,_) = x<x' )

不太有效。要创建匿名函数,请使用语法\arg -> result。如果您要编写以上代码,则结果将是返回x<x'的另一个函数:

-- \(x,_,_) -> ( \(x',_,_) -> x<x' )
-- i.e. without the parentheses:
-- \(x,_,_) -> \(x',_,_) -> x<x'

正如@WillNess所指出的,您已经在fun x < fun y的定义内进行了homerge的比较。

fun参数应该是从整个元组到要比较的部分的投影。

\(x,_,_) -> x

整个sortLastName函数如下:

sortLastName xyzs = hoMergeSort (\(name,_,_) -> name) xyzs where

如@WillNess所建议的,您可以使用where语法,该语法对于小型助手定义非常实用:

sortLastName xyzs = hoMergeSort fun xyzs where
  fun (name,_,_) = name

请注意,仅通过提供比较,您就不能轻易地颠倒顺序。如果name字段是Num,则可以返回0-x,即\(x,_,_) -> -x以降序排列,但是对于字符串,没有实际的方法。因此,最好修改hoMergeSort,使其接受两个参数的比较,而不是期望单个参数的投影。