#haskell #pattern-matching #overloading
Вопрос:
Привет, дорогие поклонники Хаскелла!
Все мои вопросы касаются — ПЕРЕГРУЖЕННОГО(?) ФУНКЦИЯ-часть, остальное я включил для полноты картины.
- Мне было интересно, имеет ли смысл использовать сопоставление шаблонов для перегрузки моего порядка функций, как я сделал в приведенном ниже примере.
- Мне также было интересно, всегда ли первая функция с вызовом функции «Баланс баланса» в первой версии функции заказа получает executerd (потому что я не выделил для нее шаблон) или никогда (потому что все шаблоны продуктов питания описаны в функциях ниже).
Заранее спасибо от новичка 🙂
-- TYPE DECLARATIONS -- data Spice = Regular | Medium | Hot data Base = Noodles | Rice data Meat = Duck | Chicken | Pork data Sauce = Tomato | Meatballs | Carbonara data Food = Indian Spice | Pasta Sauce | Chinese Base Meat data DeliveryOption = Pickup | Delivery data DeliveryTime = Immediate | Later type CreditBalance = Int data Order = O Food DeliveryOption CreditBalance data OrderStatus = Success | Pending | Declined -- OVERLOADED(?) FUNCTION -- order :: (Order, CreditBalance) -gt; OrderStatus order (O {}, balance) | not (checkBalance balance ) = Declined | ... order (O Indian {} _ _, _) | ... order (O Pasta {} _ _, _) | ... order (O Chinese {} _ _, _) | ... -- ANOTHER FUNCTION -- checkBalance :: CreditBalance -gt; Bool checkBalance balance | balance gt; 100 = True | otherwise = False
Комментарии:
1.
order
не перегружен. Отдельные определения — это просто синтаксический сахар для чего-то подобногоorder x = case x of (O {}, balance) -gt; ...
.2. итак, то, что я написал, в основном является оператором переключения, покрытым синтаксическим сахаром? Есть ли более элегантный способ разделить различные заказы на определенные виды продуктов питания?
Ответ №1:
Я не вижу ничего действительно неправильного в этом определении функции.
Предложения функций опробованы по порядку, так что первая ветвь с checkBalance
всегда будет опробована первой, а следующая охрана и так далее, и если ни одна из охранников первой группы не будет сопоставлена, то будет опробована следующая группа ( O Indian {} _ _
).
Если бы стражи первой группы были исчерпывающими, то другие ветви ниже были бы недоступны, что означало бы, что что-то не так, но трудно сказать больше без более подробной информации.
Комментарии:
1. Ну, в деталях с защитой, за которыми следуют точки, больше нет деталей (
| ...
), потому что я хотел знать, как работает порядок выполнения, прежде чем внедрять какие-либо дополнительные функции. Поэтому, если бы я хотел реализовать некоторые функции для каждой функции заказа в зависимости от типа пищи по отдельности, было бы разумнее удалить функцию первого заказа и проверить баланс в каждой функции заказа по отдельности, верно?
Ответ №2:
-- OVERLOADED(?) FUNCTION -- order :: (Order, CreditBalance) -gt; OrderStatus order (O {}, balance) | not (checkBalance balance ) = Declined | ...
Приведенный выше шаблон будет охватывать каждый случай, и все, что ниже, никогда не будет иметь возможности проверить.
Причина в том, что Order
имеет только один конструктор , а именно O
, и (O {})
, соответствует всем возможным аргументам O
конструктора. Другой член кортежа — это просто простой Int
, который всегда совпадает.
Поскольку шаблоны сопоставляются сверху вниз и выбирается первый, который соответствует, порядок их определения в коде важен. Если вы поместите максимально широкий шаблон вверху, то более конкретные, приведенные ниже, никогда не смогут совпасть.
Что касается функции перегрузки, я могу подумать о том, как можно (ab)использовать сопоставление шаблонов для имитации перегрузки функций, как в ООП, но тогда вам также потребуется (ab)использовать объявления данных и всю систему типов, чтобы согнуть их в соответствии с такой идеей, и это только ухудшит ситуацию.
Комментарии:
1. Итак, по сути, вы хотите сказать, что функция первого порядка является исчерпывающей (только для моего понимания)? Было бы разумнее удалить эту первую функцию и проверить баланс в каждой функции, где тип питания заказа подбирается индивидуально ?
2. да, вы абсолютно правы. Первая схема является исчерпывающей. И да, я бы перешел от узких моделей к более широким. Посмотрите на это как на
if elif elif elif else
конструкцию, в которой выполняется первая истинная ветвь, а последняя-это всеобъемлющий шаблон (если предыдущие еще не охватили все).3. ладно, в этом есть смысл! Есть ли более элегантный способ справиться с этим ветвлением, чем я сделал с сопоставлением шаблонов, или это хорошая практика? Я изо всех сил пытался найти решение для этой конкретной программы, потому что еда-это тип, «завернутый» в порядок типов, если вы понимаете, что я имею в виду.
4. Я думаю, что сопоставление шаблонов идеально подходит для этого случая.
5. Первый случай не является исчерпывающим, если только нет такого охранника, как
| otherwise
«цепочка». Если охранники не охватывают все случаи, то будут рассмотрены другие модели. Я думаю, что ОП хочет выразить «если у вас недостаточно денег или что-то другое, не зависящее от кухни, пойдет не так, сначала разберитесь с этим; в противном случае переходите к обработке, связанной с кухней», что будет работать нормально, как написал ОП.