Упорядочение параметров для использования карри
Недавно я дважды подверг рефакторингу код, чтобы изменить порядок параметров, потому что было слишком много кода, где хаки вроде flip
или же \x -> foo bar x 42
происходило.
При разработке сигнатуры функции какие принципы помогут мне наилучшим образом использовать карри?
3 ответа
Для языков, которые легко поддерживают каррирование и частичное применение, есть одна убедительная серия аргументов, первоначально от Криса Окасаки:
- Поместите структуру данных в качестве последнего аргумента
Зачем? Затем вы можете правильно составлять операции над данными. Например insert 1 $ insert 2 $ insert 3 $ s
, Это также помогает для функций на состоянии.
Стандартные библиотеки, такие как "контейнеры", следуют этому соглашению.
Иногда приводятся альтернативные аргументы, чтобы поставить структуру данных на первое место, чтобы ее можно было закрыть, приводя к функциям статической структуры (например, поиск), которые немного более кратки. Тем не менее, широкое согласие, похоже, заключается в том, что это менее выигрыш, тем более, что это подталкивает вас к коду в скобках.
- Поставьте самый разнообразный аргумент последним
Для рекурсивных функций обычно в качестве последнего аргумента обычно указывается аргумент, который больше всего варьируется (например, аккумулятор), а в начале аргумент, который меняет меньше всего (например, аргумент функции). Это хорошо сочетается с последним стилем структуры данных.
Сводная информация о представлении Okasaki приведена в его библиотеке Edison (опять же, другая библиотека структур данных):
- Частичное применение: аргументы, которые с большей вероятностью являются статическими, обычно появляются перед другими аргументами, чтобы облегчить частичное применение.
- Коллекция появляется последней: во всех случаях, когда операция запрашивает одну коллекцию или изменяет существующую коллекцию, аргумент коллекции будет отображаться последним. Это является стандартом де-факто для библиотек структур данных Haskell и обеспечивает определенную согласованность с API.
- Самый обычный порядок: когда операция представляет собой известную математическую функцию для нескольких структур данных, аргументы выбираются так, чтобы соответствовать наиболее обычному порядку аргументов для функции.
Поместите аргументы, которые вы, скорее всего, будете использовать в первую очередь. Аргументы функции являются отличным примером этого. Вы, скорее всего, захотите map f
более двух разных списков, чем вы хотите отобразить много разных функций в одном списке.
Я склонен делать то, что вы сделали, выбрать какой-то заказ, который кажется хорошим, и затем выполнить рефакторинг, если окажется, что другой заказ лучше Порядок во многом зависит от того, как вы собираетесь использовать функцию (естественно).