Либо Монада: Как собрать все правильные ценности и поработать со всеми из них в конце?

Поэтому я пытаюсь собрать все правильные значения из серии результатов Either и получить их все в конце цепочки для работы над ними. Я также хочу, чтобы цепочка быстро выходила из строя, если одно из значений Either равно Left.

Поэтому после прочтения я верю, что ключом к тому, чтобы все это заработало, является сочетание функции с карри и аппликативного функтора.

Ниже приведен пример кода, который у меня пока не работает. Обратите внимание, что я использую monet.js и lodash:

const test1 = Right('test1');
const test2 = Left('test2');
const test3 = Right('test3');

function success(val, val2, val3){
    return {
        val, val2, val3
    };
}

const curriedFn = _.curry(success);

Right(curriedFn)
    .ap(Right(function(fn){
        return fn(test1);
    }))
    .ap(Right(function(fn){
        return fn(test1);
    }))
    .ap(Right(function(fn){
        return fn(test1);
    }))
    .map(function(res){
        console.log(res);
    });

В самом конце я получаю объект, который содержит 3 любых значения, которые выглядят так:

{ val: { isRightValue: true, value: 'test1' },
  val2: { isRightValue: true, value: 'test1' },
  val3: { isRightValue: true, value: 'test1' } }

То, что я хочу, это 3 фактических значения. И если вы видите, одно из значений Either - это Left, и цепь должна была быть разорвана.

Я пытаюсь сделать это чисто функциональным способом. Вот почему я не отображаю и не вставляю значения в объект вне рамок функций.

Есть идеи? Альтернативы?

2 ответа

Решение

Поэтому я неправильно прочитал документы: https://monet.github.io/monet.js/

Вы должны вложить последовательный .ap звонки. Ниже приведен переработанный пример того, что я пытался сделать выше:

const test1 = Right('test1');
const test2 = Right('test2');
const test3 = Right('test3');

const success = _.curry(function (val, val2, val3){
    return {
        val,
        val2,
        val3
    };
});

test3.ap(test2.ap(test1.map(success)))
    .map(success => {
        console.log(success)
    });

Я уверен, что есть элегантный способ compose или какая-то другая монада, чтобы расплющить цепь, но пока я доволен.

Похоже, вы используете .ap неверно

const Either =
  require ('data.either')

const { Left, Right } =
  Either

const success = x => y => z =>
  [ x, y, z ]

const a =
  Right (1)

const b =
  Right (2)

const c =
  Right (3)

const badegg =
  Left ('badegg')

Если success применяется к badegg для любого параметра, немедленным результатом будет Left, Последующие звонки .ap не повлияет на Left

Right (success)
  .ap (a)
  .ap (b)
  .ap (c)
  .fold (console.error, console.log) // [ 1, 2, 3 ]

Right (success)
  .ap (badegg)
  .ap (b)
  .ap (c)
  .fold (console.error, console.log) // "badegg"

Right (success)
  .ap (a)
  .ap (badegg)
  .ap (c)
  .fold (console.error, console.log) // "badegg"

Right (success)
  .ap (a)
  .ap (b)
  .ap (badegg)
  .fold (console.error, console.log) // "badegg"
Другие вопросы по тегам