2015-07-31 2 views
1

Прежде всего, я хотел бы, чтобы вы все знали, что я очень новичок в 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.

+6

посмотрите [hoogle] (https://www.haskell.org/hoogle/?hoogle=compare) и выполните поиск: 'sortBy',' compare', 'on' и' snd' - вы можете загасить те вместе, чтобы получить именно то, что вы хотите (головоломкой вместе, я действительно говорю о * составлении *) – Carsten

+0

@Carsten: Это мог быть ответ. : D – Zeta

+0

@ Zeta у вас есть немного больше информации, хотя;) (+1) – Carsten

ответ

7

Примечание: Это сообщение написано грамотным Haskell. Вы можете сохранить его как Team.lhs и попробовать. Это, как говорится, в основном более длинная версия комментария Карстен. Если вы все еще пытаетесь разобраться в этом, используйте hoogle и ищите функции, хотя это нормально, если вы управляете вещами только с sortBy.


Прежде всего, мы будем работать в списках, так что вы хотите импортировать Data.List.

> module Team where 
> import Data.List 

Он содержит функцию под названием sortBy:

sortBy :: (a -> a -> Ordering) -> [a] -> [a] 

Первый аргумент sortBy должен быть функцией, которая сравнивает два элемента списка и возвращает

  • LT если первый меньше, чем у второго,
  • EQ если оба они равны ,
  • GT если первое больше второго.

Так что нам нужно что-то, что занимает две команды и возвращает их порядок:

> -- 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) 

Альтернативой on упоминается Carsten является on от Data.Function :

sortTeams = sortBy (compare `on` sum . snd) 
+0

Должно быть больше грамотных ответов Haskell, подобных этому :) – duplode

Смежные вопросы