Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/479.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript chainRec的基本理念是什么?_Javascript_Recursion_Functional Programming_Monads - Fatal编程技术网

Javascript chainRec的基本理念是什么?

Javascript chainRec的基本理念是什么?,javascript,recursion,functional-programming,monads,Javascript,Recursion,Functional Programming,Monads,[编辑] 这是我们的后续问题 给定的是chainRec的类型 chainRec :: ChainRec m => ((a -> c, b -> c, a) -> m c, a) -> m b 通常,chainRec与蹦床一起实现,以允许monad中的堆栈安全递归。但是,如果我们放下蹦床,我们可以实现正常功能的chainRec类型,如下所示: const chainRec = f => x => join(f(chainRec(f), of, x));

[编辑]

这是我们的后续问题


给定的是chainRec的类型

chainRec :: ChainRec m => ((a -> c, b -> c, a) -> m c, a) -> m b
通常,
chainRec
与蹦床一起实现,以允许monad中的堆栈安全递归。但是,如果我们放下蹦床,我们可以实现正常功能的
chainRec
类型,如下所示:

const chainRec = f => x => join(f(chainRec(f), of, x));
接下来,我想将其应用于递归操作:

constmap=f=>g=>x=>f(g(x));
常数join=f=>x=>f(x)(x);
常数=x=>y=>x;
常量chainRec=f=>x=>join(f(chainRec(f),of,x));
常量重复=n=>f=>x=>
chainRec((循环,完成,参数)=>
args[0]==0
?完成(参数[1])
:loop([args[0]-1,map(f)(args[1]))([n,of(x)]);
常数inc=x=>of(x+1);

重复(10)(inc)(0)(;/)错误
不知道你的
repeat
函数做什么,我想你的调用
repeat(10)(inc)(0)
应该扩展到

map(inc)(
 map(inc)(
  map(inc)(
   map(inc)(
    map(inc)(
     map(inc)(
      map(inc)(
       map(inc)(
        map(inc)(
         map(inc)(
          of(0)
         )
        )
       )
      )
     )
    )
   )
  )
 )
)
由于您的
inc
出于某种原因返回函数
\u=>Int
而不是普通的
Int
,这将调用函数
x
上的
x+1
,从而导致该函数的字符串化(
y=>x
变成
“y=>x1”
),尝试调用时将引发异常


固定后
const inc=x=>x+1
,您的
repeat
功能仍然不起作用。它需要是简单的递归,带有

const id = x => x
// rec :: ((a -> c, b -> c, a) -> c) -> a -> b
// here with c == b, no trampoline
const rec = f => x => f(rec(f), id, x) // a bit like the y combinator

const repeat = n => f => x => 
  rec((loop, done, [m, g]) =>
    m === 0
      ? done(g)
      : loop([m - 1, map(f)(g)])
  )([n, of(x)]);

repeat(10)(inc)(0)() // 10 - works!
根本不涉及monad

如果我们想使用
chainRec
,我们需要引入一些任意的monad(这里是函数monad),而
f
chainRec
的回调需要返回该monad类型的实例,而不仅仅是
循环
/
完成

chainRec :: ChainRec m => ((a -> c, b -> c, a) -> m c, a) -> m b
//                                                ^
我们只需将返回值包装在的
中即可:

const repeat = n => f => x => 
  chainRec((loop, done, [m, g]) =>
    of(m === 0
//  ^^
      ? done(g)
      : loop([m - 1, map(f)(g)])
     )
  )([n, of(x)]);
当然,现在得到一个
mb
,也就是说,所有东西都包装在另一个函数中:

repeat(10)(inc)(0)()() // 10
//                  ^^

// repeat(1)(inc)(0) expands to `of(map(inc)(of(0)))

但我怀疑这是您想要的。

您是在询问
chainRec
的基本思想还是您的具体问题?“通常
chainRec
与蹦床一起实现,以允许monad中的堆栈安全递归。”-是的,就是这样。“然而,如果我们扔下蹦床……”那么你根本不应该实现
chainRec
,而应该简单地实现
chain
。我想理解的是,如果
chainRec
本质上是
chain
通过
map
join
实现的。由于
chain
现在由两个步骤组成,我们可以将它们分开。映射发生在
f
(属于
chainRec
)和
join
自身的
chainRec
中。然后我试图通过一个人为的例子来验证这个模糊的想法,但没有成功。没有蹦床,它只会增加无意中出现类型错误的机会,混合单子类型和
c
类型。我认为这种形式只适用于理解递归的工作原理。它背后的实际想法最好通过
chainRec=f=>x=>unlaprecandchain(inLazyRecWrapper(chainRec(f)),stopUnwrap,x))
来表达。是的,这正是我想要的!我的错误是将
inc
定义为一个动作,它与
map
一起提供嵌套的函数上下文。显然,
chainRec
f
必须提供这种上下文。
repeat
这样定义显然是胡说八道。下次我应该花更多的时间来找到一个不那么做作的例子。为了避免泄漏嵌套的上下文,我实现了
chainRec=f=>x=>join(f(chainRec(f),map(join)(of),x))
@ftor我想你可以把
inc
作为一个动作,用
chain
而不是
map
来构建调用序列。尽管仍然不会使用
chainRec
,因为您永远不会对递归函数进行尾部链接call@ftor
chainRec=f=>x=>join(f(chainRec(f),map(join)(of),x))
的类型错误