Functional programming 或者Monad:如何收集所有正确的值,并在最后处理所有这些值?

Functional programming 或者Monad:如何收集所有正确的值,并在最后处理所有这些值?,functional-programming,monads,either,monetjs,Functional Programming,Monads,Either,Monetjs,所以我要做的是从一系列的结果中收集所有正确的值,并在链的末端将它们全部用于处理它们。如果其中一个值是左,我还希望链快速失效 因此,在阅读了相关内容后,我认为实现这一切的关键是将curried函数和applicative functor结合起来 下面是我到目前为止还没有完全工作的示例代码。请注意,我使用的是monet.js和lodash: const test1 = Right('test1'); const test2 = Left('test2'); const test3 = Right('

所以我要做的是从一系列的结果中收集所有正确的值,并在链的末端将它们全部用于处理它们。如果其中一个值是左,我还希望链快速失效

因此,在阅读了相关内容后,我认为实现这一切的关键是将curried函数和applicative functor结合起来

下面是我到目前为止还没有完全工作的示例代码。请注意,我使用的是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个实际值。若你们看到了,其中一个值是一个左,这个链应该已经断了

我试图以一种纯粹的功能性方式来做这件事。这就是为什么我不将值映射和填充到函数范围之外的对象中


有什么想法吗?备选方案?

看起来您使用的
.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
,则立即的结果将是
。对
.ap
的后续调用不会影响
左侧的

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"
所以我误读了文件:

您需要嵌套连续的
.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)
    });
我相信有一种优雅的方法可以用
组合
或其他单子来拉平链条,但目前我很满意