Ramda.js - propEq (String → a → Object → Boolean) - что означают эти обозначения? [Дубликат]

1

Я не понимаю эту краткую нотацию.

Два примера:

  1. propEq (String → a → Object → Boolean)

  2. sortBy (Ord b => (a → b) → [a] → [a])

Можете ли вы его расшифровать?

И да, я знаю, как найти его документы, но эта документация довольно плохо описана

propEq

Сортировать по

  • 1
    Я не знаю, что такое ramda.js, но они выглядят как сигнатуры типов.
  • 1
    Это похоже на карри тип подписи. Я бы начал с чтения (очень редкой) документации и ссылки на конкретный пример, который использует это.
Показать ещё 5 комментариев
Теги:
functional-programming
ramda.js

3 ответа

1

Это очень похоже на Haskell. В Haskell у вас есть:

sortBy :: (Ord b) => (a -> b) -> [a] -> [a]

Вещь справа - это подпись типа.

[A] - тип списков, в которых элементы имеют тип A

A → B это тип функции, которая принимает A и возвращает B.

-> является право ассоциативным: A → B → C означает A → (B → C), т.е. функцию, которая берет A и возвращает функцию, которая берет B и возвращает C

У Haskell нет списков аргументов. Вместо этого все функции отображаются так, как описано выше: функция из 2 аргументов фактически является функцией одного аргумента, который возвращает другую функцию (которая принимает другой аргумент и возвращает реальный результат). Другой способ взглянуть на это - это косоглазие и сказать, что тип функции имеет вид A1 → A2 ->... → An → R, где Ai - типы аргументов, а R - тип результата.

Идентификаторы, начинающиеся с буквы верхнего регистра, являются реальными типами. Идентификаторы, начинающиеся с строчных букв, являются переменными типа (которые могут использоваться как любой тип, который вы хотите).

=> разделяет ограничения типа от фактического типа. Здесь мы имеем Ord b, который требует, чтобы тип, используемый для b поддерживал упорядочение (т.е. операции <, >).

Объединяя все это:

sortBy - это функция, которая принимает аргумент типа a → b и возвращает результат типа [a] → [a].

Аргумент типа a → b - это еще одна функция, которая отображает значения из некоторого типа a в некоторый тип b. b должен быть упорядоченным.

Результатом типа [a] → [a] является другая функция, которая отображает списки значений типа a в списки того же типа.

Идея состоит в том, что если вы хотите отсортировать список значений, которые нельзя сравнивать напрямую, вы можете использовать sortBy со вспомогательной функцией, которая извлекает сравнительное значение из каждого элемента списка. sortBy затем возвращает отсортированный список (в соответствии со значениями сравнения).

Использование образца:

sortBy length ["don't", "fear", "the", "reaper"]
=> ["the", "fear", "don't", "reaper"]

Здесь мы используем String как наш a и Int как наш b (потому что length :: String → Int).

Обратите внимание, что приложение-функция остается ассоциативным: fxy самом деле означает (fx) y (т. fxy функцию f к аргументу x, а затем применяет результат (который должен быть другой функцией) к y).


Что касается того, как это относится к JavaScript... не знаю.

Возможно, они хотят, чтобы вы назвали его sortBy(getComparisonValue, inputList) или sortBy(getComparisonValue)(inputList)?

  • 0
    Спасибо, @melpomene. Это действительно помогло мне лучше понять эту концепцию.
1

У Рамды нет простой документации, чтобы это понять. Вот как я это интерпретирую, надеюсь, что это приносит некоторую ясность:

В ramda, большинство, если не все функции, находятся в карри. Это означает, что любую функцию в ramda можно вызвать со всеми необходимыми аргументами или меньше. Если указано меньше необходимого количества аргументов, результатом будет другая функция, которая может принимать оставшиеся аргументы. Когда функция будет полностью применена, она вернет результат.

Так, например, давайте возьмем propEq. Как вы писали, его подпись:

propEq (String → a → Object → Boolean)

Так что это значит? Сначала, что должна делать функция: она возьмет свойство от объекта по сравнению с данным объектом и вернет сравнение как логическое.

Прежде всего, самый правый атрибут - это возвращаемое значение. При полном применении propEq возвращает логическое значение. Итак, последняя часть понятна. Тогда это остается:

String → a → Object

это аргументы, о которых я упоминал выше, ключ, значение и объект. Таким образом, один действительный вызов:

R.propEq('age', 30, { age: 30 }) --> true

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

R.propEq('age')(30)({ age: 30 }) --> true
  • 0
    Мне нравится этот ответ! Спасибо @Mario F!
0

Я лично не знаю Ramda, но это довольно четко синтаксис Haskell.

f :: Type

f - это что-то типа Type. JS:

var f = Type(...)

f :: [Type]

f - список вещей, все с типом Type. JS:

var f = [Type(...), Type(...), ...]

f :: Type -> Type

f - функция, принимающая значение Type возвращающего значение Type

var f = function(t) { return Type(...) }
f(Type(...))

f :: Type -> Type -> Type

Функция arrow (->) является право-ассоциативной. Это эквивалентно

f :: Type -> (Type -> Type)

Это означает, что f принимает Type и возвращает функцию, которая принимает Type и возвращает Type. Так Haskell выполняет функции с несколькими параметрами. Этот метод называется currying

var f = function(l) { return function(r) { return Type(...) } }
f(Type(...))(Type(...))
// Ramda does dark magic that allows you to do vvvv as well
f(Type(...), Type(...))

f :: a -> b -> a

Идентификаторы нижнего регистра в типах являются переменными типа. В определении f неизвестно, что такое a и b, а внешний код может пройти все, что им нужно. Функции с переменными типа удовлетворяют "параметричности". f обещает, что ему все равно, как работают a и b, что ограничивает то, что он может сделать. В Haskell f имеет только одну возможную реализацию, которая:

var left = function(l) { return function(r) { return l } }
left(x)(y) === x
left(1)("a") === 1
// If it a Ramda function
left(1, "a") === 1

max :: Ord a => a -> a -> a

(...) => указывает "ограничение". Эта функция работает для любого типа a, если есть способ упорядочить ее, что выражается ограничением Ord a. max еще несколько параметрический: только часть он может проверить является его заказом; a он не сможет анализировать что-либо помимо этого.

var max = function(a) { return function(b) { return a > b ? a : b } }
max(1)(94) === 94
max({})(5) // Not allowed
// Since {} and 5 aren't the same type, the above call to max is bad
// JS is not strongly typed enough to warn you, but it just won't work out
max({})({})
// Object does not have an ordering to it, so the above call is bad,
// because the (Ord a) constraint is violated.

propEq :: String -> a -> Object -> Boolean

propEq берет строку, некоторое значение любого типа, Object, а затем что-то делает с ними, возвращая Boolean. Согласно документации, это может помочь

propEq :: String -> a -> (Object -> Boolean)

Это берет имя и значение свойства для этого свойства, возвращая предикат, который является истинным для сопоставления объектов.


sortBy :: (Ord b) => (a -> b) -> [a] -> [a]

sortBy принимает функцию, и для этого требуется тип возвращаемого значения. Затем он может отсортировать список a сек, с помощью функции, чтобы превратить каждый a, в b, то с помощью Ord b, чтобы выяснить, как b будет отсортирован, а затем сортировки на основе a b с.

var nameGetter = prop("name") // function(obj) { return obj.name }
sortBy(nameGetter, [{ name: "Alice" }, { name: "Charlie" }, { name: "Bob" }])
// [{ name: "Alice" }, { name: "Bob" }, { name: "Charlie" }]

Ещё вопросы

Сообщество Overcoder
Наверх
Меню