答案 0 :(得分:1)
你想要一个像
这样的功能letterFrqs :: String -> [(Char, Float)]
与
letterFrqs "PLATYPUS" == [('A',36),('P',18),('L',9),('S',9),('T',9),('U',9),('Y',9)]
给出一个
frqLetters :: String -> [(Char, Float)]
与
frqLetters "PLATYPUS" == [('A',36),('L',9),('P',18),('S',9),('T',9),('U',9),('Y',9)]
所以你需要的是
letterFrqs = sortEm . frqLetters
带
sortEm :: [(Char, Float)] -> [(Char, Float)]
我们如何撰写sortEm
?好吧,我们sort
可以Float
,sort :: [Float] -> [Float]
。我们想把这种排序提升到我们的元组中。
通常,Haskell函数有时可能具有类似名称的堂兄弟。在这种情况下,sort :: Ord a => [a] -> [a]
有一个名为sortBy :: (a -> a -> Ordering) -> [a] -> [a]
的堂兄。这里的区别在于Ord
实例是“内联的”。更具体地说,这是Ord
instance Eq a => Ord a where
compare :: a -> a -> Ordering
因此,我们注意到sortBy
仅使用定义sort
实例Ord
的确切函数替换Ord
的{{1}}约束。实际上,这正是compare
的实施方式
sort
我们可以通过在元组上编写与sort = sortBy compare
实例等效的代码来编写sortEm
,这些实例仅比较第二个元素(我们的Ord
s!)。
那我们该怎么做?好吧,我们可以将Float
实例用于Ord
。
Float
现在,聪明地看待Haskell的人可能会注意到我们也可以这样写compareOurTuples (char1, percent1) (char2, percent2) = compare percent1 percent2
sortEm = sortBy compareOurTuples
compareOurTuples
这是一种常见的习语,有点像预先编写一个“两次”的功能。它被称为compareOurTuples tup1 tup2 = compare (snd tup1) (snd tup2)
,它位于on
。
Data.Function
但是,也是一个非常常见的习惯用法,它结合了compareOurTuples = compare `on` snd
和compare
,所以即使它有一个特殊的名字。在on
我们有
Data.Ord
因此,在撰写comparing f = compare `on` f
时,我们实际上非常经济。
sortEm
这可能是某人实际编写此代码的方式。
sortEm = comparing snd
现在有点像英语。