Использование помощника карты Ramda бесточечным способом

Как я могу изменить этот код:

 map(user => assoc('isAdult', isAdult(user), user)

для работы без точек (используя Ramda). Я думал, как это сделать с помощью useWith, но не нашел работающей реализации.

Любые идеи?

import { pipe, prop, gte, __, map, assoc, sortWith, descend } from 'ramda'

const isAdult = pipe(
  prop('age'),
  gte(__, 18)
)

const func = pipe(
  map(user => assoc('isAdult', isAdult(user), user)),
  sortWith([
    descend(prop('isAdult')),
    descend(prop('age')),
  ])
)

export default func

ИЗМЕНИТЬ (подробнее):

Я хочу создать функцию, которая возвращает массив объектов, расширенный ключом isAdult. Если пользователю больше 18 лет, мы устанавливаем флаг true.

Кроме того, функция должна возвращать пользователей, отсортированных по флагу isAdult, а затем отсортированных по ключу age.

Пример данных:

const data1 = [
  {
    name: 'Cassidy David',
    email: '[email protected]',
    id: 'FC92BF1E-A6FD-E5C1-88AB-183BD1BC59C5',
    position: 1,
    age: 53,
    created_at: '2017-04-07'
  },
  {
    name: 'Gwendolyn Edwards',
    email: '[email protected]',
    id: '00000001-ED9D-3A88-0D3C-07A148FD43ED',
    position: 2,
    age: 10,
    created_at: '2016-05-21'
  },

person John Taylor    schedule 12.09.2017    source источник
comment
Можете ли вы объяснить немного больше, каков результат, которого вы хотите достичь, с примером или чем-то еще? Из кода не ясно, что вы ожидаете в качестве вывода   -  person Mario F    schedule 12.09.2017
comment
@MarioF, конечно, я только что обновил свой вопрос.   -  person John Taylor    schedule 12.09.2017


Ответы (2)


Я думаю, спорно, полезна ли попытка сделать это бесточечным.

Это вполне читабельно, как есть:

map(user => assoc('isAdult', isAdult(user), user)),

Point-free — отличная техника, которая иногда может улучшить читаемость. Но если бы это было не так, я бы не стал с этим заморачиваться.

Тем не менее, если вы хотите попробовать безточечный режим, chain, вероятно, будет наиболее полезным. Обратите внимание, как работает цепочка для функций: chain(f, g)(x) //=> f(g(x), x).

Таким образом, вы можете написать свою соответствующую часть как

map(chain(assoc('isAdult'), isAdult))

Вы можете увидеть это в действии на Ramda REPL.

person Scott Sauyet    schedule 12.09.2017
comment
крутое решение! Документы затрудняют понимание того, что chain делает только свое, имхо - person Mario F; 12.09.2017
comment
Второй пример должен прояснить ситуацию. Но если нет, думая о функциях как о цепочках, в текущей сигнатуре Chain m => (a -> m b) -> m a -> m b мы можем думать о функциях от r к чему-то как о наших цепочках и заменять все m x на (r -> x), давая (a -> (r -> b) -> (r -> a) -> (r -> b), и ассоциативность преобразует это в (a -> r -> b) -> (r -> a) -> (r -> b). Так что с x :: r и g :: x -> a получаем f :: a -> r -> b, а chain может довольствоваться только chain(f, g) = x -> f(g(x), x). - person Scott Sauyet; 12.09.2017
comment
Большое спасибо @ScottSauyet! - person John Taylor; 12.09.2017
comment
@ScottSauyet Это хорошее приложение для чтения монады. Есть ли особая причина, по которой вы поменяли аргументы на chain? Обычно я люблю писать chain(unaryF) (x => chain(unaryF) (y => of(...)). - person ; 12.09.2017
comment
@ftor: Не совсем уверен, о чем вы спрашивали. Возможно, выпуск Ramda #1936 и #1937. - person Scott Sauyet; 13.09.2017
comment
@ScottSauyet Да, спасибо! Возможно, вы также захотите рассмотреть монады состояния/записи для Ramda. Если не брать во внимание весь механизм типов в Haskell, bind — это просто (очень) особая форма композиции функций для этих монад. Введение новых монад, конечно же, потребует переименования chain, потому что в Ramda нет механизма для перегруженных функций, верно? - person ; 13.09.2017
comment
@ftor: Ramda на самом деле не предоставляет типы. Он даже не предоставляет Maybe или Either. Он ориентирован на функции, работающие с существующими типами. Но он взаимодействует со многими типами FantasyLand. Например, map делегирует функции функтору FL, если тип не предоставлен собственным кодом Ramda (массив, объект или функция в этом случае). chain аналогичен. - person Scott Sauyet; 13.09.2017
comment
@ScottSauyet Да, я знаю это. Существуют монады, связанные с алгебраическими типами данных (например, List, Maybe и т. д.), и другие, связанные с функциональными типами. Сеть Ramda (она же Reader) — одна из последних. Государство/Писатель аналогично. Все, что вам нужно, — это функции, а с помощью State вы можете делиться состоянием между вызовами функций, а с помощью Writer вы можете создавать функции, которые возвращают дополнительное значение. - person ; 13.09.2017

Хорошо, у меня есть решение, хотя довольно спорно, является ли это улучшением ясности по сравнению с тем, что у вас уже есть:

const newFields = map(pipe(isAdult, objOf('isAdult')))(data1)
zipWith(merge, data1, newFields)

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

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

РЕДАКТИРОВАТЬ: решение Скотта Сауета на самом деле довольно хорошо решает проблему.

person Mario F    schedule 12.09.2017