Мене не цікавить перше визначення - вони не допоможуть мені написати справжню програму (+1, якщо ти переконаєш мене, що я помиляюся). Будь ласка, допоможіть мені зрозуміти друге визначення. Я думаю, що карта, фільтрування та зменшення корисні: вони дозволяють мені програмувати на більш високому рівні - менше помилок, коротший і чіткіший код.
Два визначення - це одна і та ж річ. Перша заснована на формальному визначенні, і приклади, які ви наводите, - це примітивні комбінатори - найменші можливі будівельні блоки. Вони можуть допомогти вам написати справжню програму настільки, наскільки ви можете створити більш складні комбінатори. Подумайте про комбінатори, такі як S та K, як машинну мову гіпотетичного "комбінаційного комп'ютера". Фактичні комп'ютери не працюють таким чином, звичайно, тому на практиці у вас зазвичай операції вищого рівня реалізуються за лаштунками іншими способами, але концептуальна основа все ще є корисним інструментом для розуміння значення цих вищих рівнів операції.
Друге визначення, яке ви даєте, є більш неофіційним і щодо використання більш складних комбінаторів у вигляді функцій вищого порядку, які поєднують інші функції різними способами. Зауважте, що якщо основні будівельні блоки - це примітивні комбінатори, наведені вище, все , що будується з них, є функцією вищого порядку і комбінатором. Однак мовою, де існують інші примітиви, ви маєте відмінність між речами, які є або не є функціями. У цьому випадку комбінатор, як правило, визначається як функція, яка маніпулює іншими функціями загально, а не працює над будь-якими функціонувати безпосередньо.
Які ще є приклади комбінаторів, таких як карта, фільтр?
Занадто багато для переліку! Обидва перетворюють функцію, яка описує поведінку на одному значенні, у функцію, яка описує поведінку в цілій колекції. Ви також можете мати функції, які перетворюють лише інші функції, такі як їх складання в кінці або розділення та рекомбінація аргументів. Ви можете мати комбінатори, які перетворюють одномоментні операції в рекурсивні операції, які виробляють або споживають колекції. Або всілякі інші речі, насправді.
Які комбінатори часто застосовують мови програмування?
Це буде досить різнитися. Існує порівняно небагато абсолютно загальних комбінаторів - в основному первісних згаданих вище - тому в більшості випадків комбінатори матимуть певну інформацію про будь-які використовувані структури даних (навіть якщо ці структури даних так чи інакше побудовані з інших комбінаторів), в яких У випадку, як правило, існує декілька "повністю загальних" комбінаторів, а потім будь-які різні спеціалізовані форми хтось вирішив надати. Існує смішна кількість випадків, коли (відповідно узагальнені версії) карти, складання та розгортання вистачають, щоб зробити майже все, що ви хочете.
Як комбінатори можуть допомогти мені розробити кращий API?
Точно так, як ви сказали, думкою про операції високого рівня та про те, як вони взаємодіють, а не деталі низького рівня.
Подумайте про популярність циклів стилів "для кожного" над колекціями, які дозволять вам абстрагуватися над деталями перерахування колекції. Це в більшості випадків просто операції зі складанням карт / складок, і, зробивши комбінатор (а не вбудований синтаксис), ви можете робити такі речі, як взяти дві існуючі петлі та безпосередньо комбінувати їх декількома способами - вкладати один всередину іншого, робіть одну за одною і так далі - просто застосувавши комбінатор, а не жонглюючи цілою купою коду.
Як створити ефективні комбінатори?
Спочатку подумайте, які операції мають сенс для будь-яких даних, які використовує ваша програма. Потім подумайте, як ці операції можуть бути змістовно поєднані загальними способами, а також про те, як операції можна розбити на більш дрібні шматки, які з'єднані назад. Головне - працювати з перетвореннями і операціями , а не прямими діями . Якщо у вас є функція, яка просто непрозоро виконує якийсь складний біт функціональності і випльовує лише якийсь заздалегідь засвоєний результат, з цим не багато чого. Остаточні результати залиште в коді, який використовує комбінатори - ви хочете, щоб речі, які ведуть вас з точки А до точки В, а не речі, які очікують на початок чи кінець процесу.
Чим подібні комбінатори у нефункціональній мові (скажімо, Java), або що ці мови використовують замість комбінаторів?
Ахахахаха. Смішно запитати, адже об'єкти - це справді речі вищого порядку - вони мають деякі дані, але вони також здійснюють купу операцій, і досить багато того, що є гарним дизайном OOP, зводиться до "об'єктів повинні зазвичай діють як комбінатори, а не структури даних ".
Тому, мабуть, найкраща відповідь тут полягає в тому, що замість речей, що нагадують комбінатори, вони використовують класи з безліччю методів геттера та сеттера або публічних полів та логікою, яка здебільшого полягає у виконанні певних непрозорих заздалегідь визначених дій.