чому народна казка та рамда такі різні?


96

Я вчуся яваскрипт FP читаючи DrBoolean в книгу .

Я шукав бібліотеку функціонального програмування. Я знайшов Рамду і Фольктале. Обидва претендують на функціональну бібліотеку програмування.

Але вони такі різні:

  • Здається, Ramda містить корисні функції для роботи зі списком: картографування, зменшення, фільтрування та чисті функції: каррі, складання. Він не містить нічого, що стосується монади, функтора.

  • Однак Folktale не містить жодної утиліти для списку або функцій. Здається, це реалізує деякі алгебраїчні структури в javascript, як monad: Можливо, Завдання ...

Насправді я знайшов більше бібліотек, всі вони, здається, належать до двох категорій. Підкреслення та лодаш - це як у Рамди. Fantasy-land, pointfree-fantasy схожі на казку.

Чи можна ці дуже різні бібліотеки назвати функціональними , і якщо так, то що робить кожну з них функціональною?


1
використовуйте те, що відповідає вашим потребам і стилю, і це добре задокументовано
charlietfl

1
я виявив, що насправді є три загальноприйняті значення для "функціонального програмування", особливо в JS. 1. з використанням чистих функцій вищого порядку на безлічі , як масиви., Колишній [1,2,3].map(fnSquare).reduce(fnSum)2. в основному теоретичний «погляд му не вар » Y-комбінатор-еск структури. 3. за допомогою Function.prototypeдля модифікації поведінки інших функцій, наприкладvar isMissingID=fnContains.partial("id").negate();
dandavis

10
Автор Ramda тут: Ramda - це досить низькорівнева бібліотека. Він призначений спростити певний функціональний стиль у JS, особливо працюючи за допомогою складання функцій. Ramda добре працює зі специфікацією FantasyLand, включаючи її реалізації, такі як Folktale. Ці бібліотеки розроблені з дещо іншою метою. Вони побудовані навколо розпізнавання загальноприйнятих абстрактних типів даних і забезпечення постійного доступу до них: таких речей, як Моноїди, Функціонери та Монади. Рамда буде працювати з ними, і у нього є допоміжний проект, щоб створити такий, але це, як ви кажете, зовсім інший фокус.
Скотт Соє

1
@KeithNicholas: Так, є кімната
Gitter

2
Погляньте також на Sanctuary - github.com/plaid/sanctuary Це засновано на рамді, але також охоплює типи фантастичних земель.
arcseldon

Відповіді:


180

Функціональні особливості

Не існує чітко визначеної межі того, що визначає функціональне програмування чи функціональну бібліотеку. У Javascript вбудовано деякі особливості функціональних мов:

  • Першокласні функції вищого порядку
  • Функції лямбда / анонім, із закриттям

Інші можливості можна виконати в Javascript з певною обережністю:

  • Незмінність
  • Довідкова прозорість

Інші є частиною ES6 і частково або повністю доступні зараз:

  • Компактні, навіть стислі функції
  • Рекурсія виконання завдяки оптимізації зворотного виклику

І є багато інших, які насправді виходять за рамки звичайного досяжності Javascript:

  • Відповідність шаблону
  • Ледача оцінка
  • Гомоіконічність

Тоді бібліотека може вибирати ті функції, які вона намагається підтримувати, і все ще обгрунтовано їх можна назвати "функціональними".

Специфікація фантастичної землі

Fantasy-земля є специфікацією для ряду стандартних типів , перенесених з математичної теорії категорій і загальна алгебри для функціонального програмування, таких типів, як Monoid , функтор і Монада . Ці типи досить абстрактні і поширюють, можливо, більш звичні поняття. Наприклад, функтори - це контейнери, які можна переглядати mapза допомогою функції, як можна обробляти масив mapза допомогоюArray.prototype.map .

Народна казка

Folktale - це колекція типів, що реалізують різні частини специфікації Fantasy-land та невелика колекція супутніх функцій корисності. Це такі речі, як " Можливо" , " Або" , " Завдання" (дуже схоже на те, що в інших місцях називається "Майбутнє", і більш законний двоюрідний брат "Обіцянку"), і " Валідація"

Folktale - це, мабуть, найвідоміша реалізація специфікації Fantasy-land, і її поважають. Але не існує такого поняття, як остаточна реалізація або реалізація за замовчуванням; fantasy-land вказує лише абстрактні типи, і реалізація, звичайно, повинна створити такі конкретні типи. Претензія Folktale щодо функціональної бібліотеки очевидна: вона надає типи даних, які зазвичай зустрічаються у функціональних мовах програмування, що значно спрощує функціональне програмування.

Цей приклад із документації Folktale ( примітка : не в останніх версіях документів) показує, як він може бути використаний:

// We load the library by "require"-ing it
var Maybe = require('data.maybe')

// Returns Maybe.Just(x) if some `x` passes the predicate test
// Otherwise returns Maybe.Nothing()
function find(predicate, xs) {
  return xs.reduce(function(result, x) {
    return result.orElse(function() {
      return predicate(x)?    Maybe.Just(x)
      :      /* otherwise */  Maybe.Nothing()
    })
  }, Maybe.Nothing())
}

var numbers = [1, 2, 3, 4, 5]

var anyGreaterThan2 = find(function(a) { return a > 2 }, numbers)
// => Maybe.Just(3)

var anyGreaterThan8 = find(function(a) { return a > 8 }, numbers)
// => Maybe.Nothing

Рамда

Рамда (застереження: я один з авторів) - це зовсім інший тип бібліотеки. Він не надає нових типів для вас. 1 Натомість він надає функції, що полегшують роботу з існуючими типами. Він побудований навколо уявлень про складання менших функцій у більші, про роботу з незмінними даними, про уникнення побічних ефектів.

Рамда працює особливо на списках, але також на об'єктах, а іноді і на струнах. Він також делегує багато своїх дзвінків таким чином, що він буде взаємодіяти з Folktale або іншими реалізаціями Fantasy-land. Наприклад, mapфункція Рамди працює так само , як і функція on Array.prototype, таким чином R.map(square, [1, 2, 3, 4]); //=> [1, 4, 9, 16]. Але оскільки Folktale's Maybeреалізує Functorспецифікацію Fantasy-land , яка також визначає карту, ви також можете використовувати mapз нею Ramda :

R.map(square, Maybe.Just(5)); //=> Maybe.Just(25);
R.map(square, Maybe.Nothing); //=> Maybe.Nothing

Претензії Рамди як функціональної бібліотеки полягають у спрощенні складання функцій, ніколи не мутують ваші дані і представляють лише чисті функції. Типовим використанням Рамди було б створення більш складних функцій шляхом складання менших, як видно з статті про філософію Рамди

// :: [Comment] -> [Number]  
var userRatingForComments = R.pipe(
    R.pluck('username')      // [Comment] -> [String]
    R.map(R.propOf(users)),  // [String] -> [User]
    R.pluck('rating'),       // [User] -> [Number]
);

Інші бібліотеки

Насправді я знайшов більше бібліотек, вони, здається, потрапляють у дві категорії. підкреслення, лодаш дуже схожий на Рамду. Fantasy-land, pointfree-fantasy схожі на казку.

Це насправді не точно. Перш за все, Fantasy-land - це просто специфікація, яку бібліотеки можуть вирішити застосувати для різних типів. Folktale - одна з багатьох реалізацій цієї специфікації, мабуть, найкраща, безумовно, одна з найбільш зрілих. Pointfree-fantasy та ramda-fantasy - це інші, а їх набагато більше .

Підкреслення та лодаш зовні нагадують Рамду, оскільки вони є бібліотеками для захоплення, забезпечуючи велику кількість функцій з набагато меншою згуртованістю, ніж щось на зразок Folktale. І навіть конкретна функціональність часто накладається на функцію Рамди. Але на більш глибокому рівні Рамда сильно відрізняється від цих бібліотек. Близько кузени Ramda є , ймовірно , бібліотеки FKit , Fnuc і Wu.js .

Білбі є власною категорією, що надає як ряд інструментів, таких як Рамда, так і деякі типи, що відповідають Fantasy-land. (Автор Білбі також є оригінальним автором Fantasy-land.)

Твій дзвінок

Усі ці бібліотеки мають право називатися функціональними, хоча вони сильно відрізняються за функціональним підходом та ступенем функціональної відданості.

Деякі з цих бібліотек насправді добре працюють разом. Рамді слід добре працювати з Folktale чи іншими реалізаціями Fantasy-land. Оскільки їхні занепокоєння ледве перекриваються, вони дійсно не конфліктують, але Рамда робить це достатньо, щоб зробити взаємодію відносно гладкою. Це, мабуть, менш вірно для деяких інших комбінацій, які ви можете вибрати, але простіший синтаксис функцій ES6 також може позбавити біль від інтеграції.

Вибір бібліотеки чи навіть стилю бібліотеки для використання буде залежати від вашого проекту та ваших уподобань. Є багато хороших варіантів, і кількість зростає, і багато з них значно покращуються. Настав час зайнятися функціональним програмуванням у JS.


1 Ну, є побічний проект, ramda фантазії робити що - щось подібне до того , що робить Народна казка, але це не є частиною основної бібліотеки.


1
Чи справедливо було б сказати, що ES6 має можливість лінивого оцінювання з введенням Yield? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Марсель Ламоте

8
Ні. yieldСпрощує різновиди лінивої обробки списків, виконаних Lazyабо lz.js. Але це не допомагає при ліні на рівні мови. someFunc(a + b)в JS спочатку додає значення, aа bпотім постачає результат як параметр до someFunc. Еквівалент у Хаскелі цього не робить. Якщо функція, що викликається, ніколи не використовує це значення, вона ніколи не виконує додавання. Якщо воно врешті-решт використовує його, вважається виразом, який потрібно обчислювати, поки не буде потрібний його результат. Якщо ви ніколи не зробите нічого, що змусить це (як IO), він фактично не виконає обчислення.
Скотт Сауєт

@ScottSauyet, можливо, ви можете стверджувати, що "лінива оцінка" в якійсь формі доступна, наприклад, через генератори ES6 - багато JS-фреймворки мають "ліниві" характеристики - RxJ, ImmutableJs тощо
arcseldon

8
Ця відповідь повинна бути розділом або розділом книги DrBoolean. :)
Сет

1
Документація Ramda, як правило, використовує "list" як скорочення для найближчого, що JS пропонує до списків, щільних масивів. Вони мають різні характеристики продуктивності, ніж чисті списки, і, звичайно, дещо інший API, але вони можуть бути використані для майже однакових цілей, і вони є найближчим типовим (але див. Github.com/funkia/list ) типом, доступним для Ramda's API, який концептуально хоче працювати з чистими списками. Я б аргументував неправдиві пункти масивів, оскільки масиви у стилі С не є більш канонічними, ніж JS, і жоден насправді не наближається до математичних, але це другорядний момент.
Скотт Сауєт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.