Haskell: функция значения

Я все еще делаю упражнение из книги, и одно упражнение говорит, что я должен создать функцию: value :: Hand -> Int, которая возвращает значение руки.

Мой код пока выглядит так:

data Hand = PairOf Rank | ThreeOf1 Rank | ThreeOf2 Suit
           
value: Hand -> Int
otherwise = 0
-- 

Теперь у меня другая проблема, потому что я не знаю, как описать «Ничто». Здесь ничего не описано как возможная комбинация рук, в которой не встречаются Pair, ThreeOf1 и ThreeOf2. В противном случае = 0 будет работать или это не имеет особого смысла?

Еще раз спасибо за предложения, я их исправил! Также заранее спасибо за разъяснения и помощь.

«или их ранги равны, а масти решают» Это не то, что на самом деле делает ваша функция. "2 карты одного ранга" Тогда почему вы дважды включаете ранг? Вы можете включить ранг и две масти, если хотите, чтобы значение Hand представляло уникальную руку. То же самое и во всех остальных случаях. «Я точно не знаю, как создать функцию значения». Используйте сопоставление с образцом. Любой учебник или учебник по Haskell должен объяснять это на одной из первых страниц.

n. m. 20.11.2022 11:41

Вероятно, использование Nothing в качестве одного из ваших конструкторов — плохая идея, так как Nothing уже используется библиотекой Haskell в качестве конструктора Maybe.

jpmarinier 20.11.2022 13:21

У вас могут быть предложения сопоставления с образцом в вашей функции value, например: value (Flush s0 s1 s2) = 3

jpmarinier 20.11.2022 13:23

«... или их ранги равны, и решают масти». - Но Haskell по умолчанию использует лексикографический порядок, так что это именно то, что вы получите, просто используя deriving (Show, Eq, Ord)

jpmarinier 20.11.2022 13:38

Некоторые из ваших конструкторов Hand слишком общие. PairOf Seven Seven имеет смысл, конечно, но как насчет PairOf Seven Eight. PairOf сама по себе уже подразумевает две карты равного достоинства; вам нужно только указать, какой это ранг. PairOf Rank достаточно. То же самое относится и к ThreeOf и Flush (флеш — это уже все карты одной масти; просто назовите ту масть, которая является общей для всех карт, а не идентичную масть каждой карты в отдельности).

chepner 20.11.2022 14:52

Спасибо всем! Я понял это, и теперь это работает, но как я могу сделать это с помощью Nothing? не могли бы вы подсказать и объяснить?

user20549332 20.11.2022 15:25

Где вы дали указание использовать такой тип данных Hand? На мой взгляд, более сложным (и интересным) является просмотр группы карт и вычисление того, есть ли у вас пара, тройка, флеш и т. д. Ваша функция value начинается с типа, который фактически уже содержит информацию о какое там значение (поэтому вы можете игнорировать все фактическое содержимое конструкторов Hand; значение уже определяется тем, какой конструктор был там). Но это еще не позволило бы вам определить ценность произвольного набора из 5 карт.

Ben 21.11.2022 03:42

то есть я ожидал, что value :: Hand -> Int будет сочетаться с чем-то вроде type Hand = [Card], а не data Hand = PairOf ... | .... Но, возможно, они подготавливают вас к другой функции, которая позже перейдет от [Card] к Hand.

Ben 21.11.2022 03:44
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
8
154
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

otherwise здесь не работает. Вам нужен неопровержимый шаблон, который будет соответствовать чему угодно, и, кроме того, поскольку вам все равно, что совпадет, вам нужен именно шаблон _:

value :: Hand -> Int
value (PairOf r1) = 1
value (ThreeOf r1) = 2
value (Flush s1) = 3
value _ = 0

Поскольку вам все равно, какую пару вы получите и т. д., вы также можете использовать _ в других случаях:

value :: Hand -> Int
value (PairOf _) = 1
value (ThreeOf _) = 2
value (Flush _) = 3
value _ = 0

Если вы хотите сопоставить Nothing (или любое другое имя, которое вы придумаете, которое не конфликтует с конструктором Maybe), это просто

value Nothing = 0

Одна из проблем, с которой вы можете столкнуться, заключается в том, что Ничто не существует.

Вот полный тип рук для холдема:

data HandRank
  = HighCard Rank Rank Rank Rank Rank
  | OnePair Rank Rank Rank Rank
  | TwoPair Rank Rank Rank
  | ThreeOfAKind Rank Rank Rank
  | Straight Rank
  | Flush Rank Rank Rank Rank Rank
  | FullHouse Rank Rank
  | FourOfAKind Rank Rank
  | StraightFlush Rank
  deriving (Eq, Ord, Show, Generic)

Дополнительные ранги в типе данных предназначены для различения рук, поэтому пара тузов с кикером короля и дамы бьет пару тузов с кикером короля и валета. Но в остальном это то же самое, что и ваша установка.

Как только у вас есть полное преобразование из набора карт в ценность руки, нет ничего. То, о чем вы, возможно, подумали как о чем-то, это линия HighHand в типе суммы. Если ваш контекст подходит для возможных рук, то я бы добавил NoValue к типу суммы рук, что лучше, чем вывод Maybe Hand.

Использование подстановочных знаков otherwise _ или value _ может привести к ошибке, потому что вы можете забыть о кодировании, скажем, фулл-хауса, и ваша существующая функция будет работать. Если вы забудете закодировать один из типов суммы и у вас нет шаблона match-any, компилятор будет жаловаться. Предоставление компилятору всех ветвей типа суммы также является горячей областью разработки GHC, и это будет быстро.

Другие вопросы по теме