如何为应用计算实现协程?

时间:2019-02-02 18:36:46

标签: javascript functional-programming monads functor applicative

下面是一种避免像嵌套图案的协程(chain(m) (chain(...))为一元计算:

const some = x => none => some => some(x);
const none = none => some => none;

const option = none => some => tx => tx(none) (some);
const id = x => x;

const of = some;
const chain = fm => m => none => some => m(none) (x => fm(x) (none) (some));

const doM = (chain, of) => gf => {
  const it = gf();

  const loop = ({done, value}) =>
    done
      ? of(value)
      : chain(x => loop(it.next(x))) (value);

  return loop(it.next());
};

const tx = some(4),
  ty = some(5),
  tz = none;

const data = doM(chain, of) (function*() {
  const x = yield tx,
    y = yield ty,
    z = yield tz;

  return x + y + z;
});

console.log(
  option(0) (id) (data)); // 0

但是我无法为应用计算实现等效的协程:

const some = x => none => some => some(x);
const none = none => some => none;

const option = none => some => tx => tx(none) (some);
const id = x => x;

const of = some;
const map = f => t => none => some => t(none) (x => some(f(x)));
const ap = tf => t => none => some => tf(none) (f => t(none) (x => some(f(x))));

const doA = (ap, of) => gf => {
  const it = gf();

  const loop = ({done, value}, initial) =>
    done
      ? value
      : ap(of(x => loop(it.next(x)))) (value);

  return loop(it.next());
};

const tx = some(4),
  ty = some(5),
  tz = none;

const data = doA(ap, of) (function*() {
  const x = yield tx,
    y = yield ty,
    z = yield tz;

  return x + y + z;
});

console.log(
  option(0) (id) (data)); // none => some => ...

这应该工作,但事实并非如此。哪里额外函子包装从何而来?我想我在递归中有点迷路了。

据我所知,这仅适用于确定性函子/单子。

1 个答案:

答案 0 :(得分:2)

  

我无法为应用计算实现等效的协程

是的,因为生成器函数是一元函数,而不仅仅是适用函数。一个#include <stdio.h> #include <string.h> #include <malloc.h> int main() { char* arr[2][2]; char str[20]; for(int i = 0; i < 2; i++){ for (int j = 0; j < 2; j++){ printf("%s", "please put in a string: "); if (scanf("%s", &str[0]) == 1) { arr[i][j] = (char*)malloc(20*sizeof(char)); strncpy(arr[i][j], str, 20); } } } for(int i = 0; i < 2; i++){ for (int j = 0; j < 2; j++){ printf("arr[%d][%d] == %s\n", i,j, arr[i][j]); } } return 0; } 表达式的操作数可以取决于先前的yield表达式的结果 - ,对于一个单子的特性

  

附加函子包装来自何处?我想我在这里有点迷路了。

您正在做yield-根据Applicative laws,这相当于ap(of(…))(…)。与第一个代码段中的map(…)(…)调用相比,此操作不会对结果进行任何拆包,因此您获得了嵌套的chain类型(在您的实现中被编码为一个函数)。