Function 将列表排序为元组

Function 将列表排序为元组,function,sorting,haskell,Function,Sorting,Haskell,我是Haskell的新手,正在尝试使用第一个元素(使用sort函数)对元组列表进行排序。因此,如果我有[a,b,a,c,c],我会得到类似于[1,b,2,a,2,c]的东西,在相同数字的情况下按字母顺序排列 我该怎么做呢?我现在完全迷路了……我仍在试图进入“哈斯克尔思维方式” import Data.List (sort, group) import Control.Arrow ((&&&)) answer :: Eq a => [a] -> [(Int,

我是Haskell的新手,正在尝试使用第一个元素(使用sort函数)对元组列表进行排序。因此,如果我有[a,b,a,c,c],我会得到类似于[1,b,2,a,2,c]的东西,在相同数字的情况下按字母顺序排列

我该怎么做呢?我现在完全迷路了……我仍在试图进入“哈斯克尔思维方式”

import Data.List (sort, group)
import Control.Arrow ((&&&))

answer :: Eq a => [a] -> [(Int, a)]
answer = sort . map (length &&& head) . group . sort
但是,由于您是初学者,可能有很多东西要告诉您,因此我将这样重写:

import Data.List (sort, group)

answer :: Eq a => [a] -> [(Int, a)]
answer = sort . map f . group . sort
  where f xs @ (x:_) = (length xs, x)
你会注意到我给sort打了两次电话。这是故意的

最后一个排序——左边的那个排序——对元组的输出列表进行排序,恰好它按照元组的第一个元素的升序排序,通过对元组的第二个元素进行排序打破了联系

右边的初始排序对输入列表进行排序,因为它将相邻的相等元素分组到一个子列表中。顺便说一句,这些子列表保证永远不会为空,否则在模式匹配中使用head或忽略空列表选项是不安全的

然后映射f将这些列表(例如[a,a])转化为我们感兴趣的内容:这些元素出现的次数,以及这些元素的单个代表,例如2,a

这里的习惯用法是我们使用一个管道:我们的输入进入一个函数,该函数的输出进入另一个函数,依此类推,直到管道末端的函数产生我们作为自己的输出呈现的输出。请注意,这仅适用于每个函数,因为每个函数只接受一个参数。map接受两个参数,f是这些参数中的第一个,因此map f接受一个参数

因此,答案是一个函数,即使它的参数没有显式出现。这是无点风格

在非点自由样式中,它看起来像

answer xs = sort . map f . group . sort $ xs
  where f xs @ (x:_) = (length xs, x)

当无点样式使代码更清晰时,使用它是一个好主意


如果您愿意,您可以使用示例中可能的重复项。预期的转换是明确的,但是[a,b,a,…]不是元组列表,因此对元组列表进行排序只是任务的一部分。此任务的更好措辞方式是“将平面列表转换为表示为计数、元素元组列表的平面列表”。
answer xs = sort $ map f $ group $ sort xs
  where f xs @ (x:_) = (length xs, x)
answer xs = sort (map f (group (sort xs)))
  where f xs @ (x:_) = (length xs, x)
import Data.List (sort, group)
import Control.Arrow ((<<<))

answer :: Eq a => [a] -> [(Int, a)]
answer = sort <<< map f <<< group <<< sort
  where f xs @ (x:_) = (length xs, x)
import Data.List (sort, group)
import Control.Arrow ((>>>))

answer :: Eq a => [a] -> [(Int, a)]
answer = sort >>> group >>> map f >>> sort
  where f xs @ (x:_) = (length xs, x)