从定义中写一个函数?
Writing a function from definitions?
首先,我想让你们都知道我是 Haskell 的新手,所以为了增加知识等,我一直在尝试问题,但我很困在一个问题上.我想我快到了,但我们将不胜感激一些更有经验的建议。这是问题:
一个运动队由它的名字和他们在上一场比赛中得分的数量来代表 ("Newcastle",[3,3,3,0])
。此数据由类型定义建模:
type TName = String
type Points = [Int]
type Team = (TName,Points)
据此我必须定义以下函数,如果他们的积分总和更大,则将一个团队排序为高于另一个团队:
sortPoints :: [Team] -> [Team]
这是我试过的:
sortPoints :: [Team] -> [Team]
sortPoints [_,()] -> []
sortPoints [_,(x:xs)] = sum[x|x<-xs]
一旦我到达这里,我不太确定如何添加条件来检查积分总和,任何指针将不胜感激,因为我仍然接受很多 Haskell 特征。
注:此post是文体Haskell写的。您可以将其保存为 Team.lhs
并尝试一下。也就是说,它基本上是 Carsten 评论的加长版。如果您仍然试图解决问题,请使用 hoogle 并查找函数,尽管如果您首先使用 sortBy
来管理事情也很好。
首先,我们将处理列表,因此您要导入 Data.List
。
> module Team where
> import Data.List
它包含一个名为 sortBy
的函数:
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
sortBy
的第一个参数应该是一个比较列表中两个元素的函数,returns
LT
如果第一个小于第二个,
EQ
如果两者相等,
GT
如果第一个大于第二个。
所以我们需要需要两个团队和 returns 他们的排序的东西:
> -- Repeating your types for completeness
> type TName = String
> type Points = [Int]
> type Team = (TName, Points)
>
> compareTeams :: Team -> Team -> Ordering
现在,您想根据分数的总和来比较球队。您不需要他们的名字,因此您可以只捕获该对的第二部分:
> compareTeams (_, s1) (_, s2) =
我们需要积分的总和,所以我们定义sum1
和sum2
为球队各自的总和:
> let sum1 = sum s1
> sum2 = sum s2
现在我们可以比较这些总和了:
in if sum1 < sum2
then LT
else if sum1 == sum2
then EQ
else GT
然而,这相当冗长,并且已经有一个类型为 Ord a => a -> a -> Ordering
的函数。它被称为 compare
并且是 Prelude
:
的一部分
> in sum1 `compare` sum2
这样就简洁多了。现在我们可以很容易地定义sortTeams
:
> sortTeams :: [Team] -> [Team]
> sortTeams = sortBy compareTeams
就是这样,我们完成了!
好吧,我撒谎了,我们还没有 100% 完成。模块 Data.Ord
包含一个名为 comparing
的函数,它非常方便:
comparing :: Ord b => (a -> b) -> a -> a -> Ordering
comparing f x y = f x `compare` f y -- or similar
与 snd
和 sum
一起,您可以在一行中定义 sortTeams
:
sortTeams = sortBy (comparing $ sum . snd)
Carsten 提到的备选 on
是 on
来自 Data.Function
:
sortTeams = sortBy (compare `on` sum . snd)
首先,我想让你们都知道我是 Haskell 的新手,所以为了增加知识等,我一直在尝试问题,但我很困在一个问题上.我想我快到了,但我们将不胜感激一些更有经验的建议。这是问题:
一个运动队由它的名字和他们在上一场比赛中得分的数量来代表 ("Newcastle",[3,3,3,0])
。此数据由类型定义建模:
type TName = String
type Points = [Int]
type Team = (TName,Points)
据此我必须定义以下函数,如果他们的积分总和更大,则将一个团队排序为高于另一个团队:
sortPoints :: [Team] -> [Team]
这是我试过的:
sortPoints :: [Team] -> [Team]
sortPoints [_,()] -> []
sortPoints [_,(x:xs)] = sum[x|x<-xs]
一旦我到达这里,我不太确定如何添加条件来检查积分总和,任何指针将不胜感激,因为我仍然接受很多 Haskell 特征。
注:此post是文体Haskell写的。您可以将其保存为 Team.lhs
并尝试一下。也就是说,它基本上是 Carsten 评论的加长版。如果您仍然试图解决问题,请使用 hoogle 并查找函数,尽管如果您首先使用 sortBy
来管理事情也很好。
首先,我们将处理列表,因此您要导入 Data.List
。
> module Team where
> import Data.List
它包含一个名为 sortBy
的函数:
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
sortBy
的第一个参数应该是一个比较列表中两个元素的函数,returns
LT
如果第一个小于第二个,EQ
如果两者相等,GT
如果第一个大于第二个。
所以我们需要需要两个团队和 returns 他们的排序的东西:
> -- Repeating your types for completeness
> type TName = String
> type Points = [Int]
> type Team = (TName, Points)
>
> compareTeams :: Team -> Team -> Ordering
现在,您想根据分数的总和来比较球队。您不需要他们的名字,因此您可以只捕获该对的第二部分:
> compareTeams (_, s1) (_, s2) =
我们需要积分的总和,所以我们定义sum1
和sum2
为球队各自的总和:
> let sum1 = sum s1
> sum2 = sum s2
现在我们可以比较这些总和了:
in if sum1 < sum2
then LT
else if sum1 == sum2
then EQ
else GT
然而,这相当冗长,并且已经有一个类型为 Ord a => a -> a -> Ordering
的函数。它被称为 compare
并且是 Prelude
:
> in sum1 `compare` sum2
这样就简洁多了。现在我们可以很容易地定义sortTeams
:
> sortTeams :: [Team] -> [Team]
> sortTeams = sortBy compareTeams
就是这样,我们完成了!
好吧,我撒谎了,我们还没有 100% 完成。模块 Data.Ord
包含一个名为 comparing
的函数,它非常方便:
comparing :: Ord b => (a -> b) -> a -> a -> Ordering
comparing f x y = f x `compare` f y -- or similar
与 snd
和 sum
一起,您可以在一行中定义 sortTeams
:
sortTeams = sortBy (comparing $ sum . snd)
Carsten 提到的备选 on
是 on
来自 Data.Function
:
sortTeams = sortBy (compare `on` sum . snd)