Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.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
Haskell OCaml参数传递方案中的断点_Haskell_Ocaml_Ocaml Core - Fatal编程技术网

Haskell OCaml参数传递方案中的断点

Haskell OCaml参数传递方案中的断点,haskell,ocaml,ocaml-core,Haskell,Ocaml,Ocaml Core,今天,我正在浏览的是'sCore\u kernel模块的源代码,我使用了compose函数: (*这些函数的典型用例是传入函数参数 因此,我们告诉编译器 在参数传递方案中插入断点。*) 设f g=();乐趣x->f(gx) 我会将compose函数定义为: 让组合f g x=f(g x) 他们这样定义compose的原因是“因为compose是一个函数,它将函数f和g作为参数,并返回函数fun x->f(gx)因此,他们定义了compose的方法,即告诉编译器在参数传递方案中的f和g之后但在

今天,我正在浏览的是's
Core\u kernel
模块的源代码,我使用了
compose
函数:

(*这些函数的典型用例是传入函数参数
因此,我们告诉编译器
在参数传递方案中插入断点。*)
设f g=();乐趣x->f(gx)
我会将
compose
函数定义为:

让组合f g x=f(g x)
他们这样定义
compose
的原因是“因为
compose
是一个函数,它将函数
f
g
作为参数,并返回函数
fun x->f(gx)
因此,他们定义了
compose
的方法,即告诉编译器在参数传递方案中的
f
g
之后但在
x
之前插入断点。”

所以我有两个问题:

  • 为什么在参数传递方案中需要断点
  • 如果我们以正常的方式定义
    compose
    会有什么不同

  • 来自Haskell,这个约定对我来说没有任何意义。

    这是一个效率黑客,以避免在注释中指出的预期用例中部分应用程序的成本

    OCaml将curried函数编译成固定的arity构造,必要时使用闭包部分应用它们。这意味着该arity的调用是有效的——没有闭包构造,只有一个函数调用

    对于
    funx->f(gx)
    ,在
    compose
    中将有一个闭包构造,但这将比部分应用程序更有效。部分应用程序生成的闭包要经过一个包装器
    caml\u curryN
    ,该包装器的存在是为了确保效果在正确的时间发生(如果闭包本身部分应用)

    编译器选择的固定算术是基于一个简单的语法分析——本质上,一行中有多少个参数,中间没有任何内容。Jane St.程序员已经用它通过注入
    ()
    “中间”参数来选择他们想要的算术

    简而言之,
    let compose f g x=f(g x)
    是一个不太理想的定义,因为它会导致
    compose f g
    的常见双参数情况成为一个更昂贵的部分应用程序


    当然,在语义上没有任何区别。

    值得注意的是,OCaml中部分应用程序的编译已经得到了改进,这种性能攻击不再是必要的。

    是否会构建一个闭包来返回
    fun x->f(gx)
    ?与部分应用程序相关的关闭相比,创建此关闭是否更便宜?我看不出一个明显的原因。由部分应用程序构建的闭包涉及一个额外的间接过程-它们通过
    caml\u curryN
    (这对于正确的求值顺序是必要的),而不是直接到代码。编译器不处理
    let compose f g=fun x->f(gx)吗
    让f g x=f(g x)
    以不同的方式组合?我不会想到插入一个
    ()
    。不,这些都是一样处理的
    let f x y=…
    只是
    let f=fun x->fun y->…
    的糖:展开时,两者是相同的。明白了。在Haskell中,内联线对它们的处理略有不同。使用
    ()很有意义;不过,在OCaml中也有类似的技巧。当影响内联线时,Haskell中也会发生类似的事情。下面的映射定义比更简单的定义优化得更好:
    map f=go where{go[]=[];go(a:as)=f a:go as}
    @J.Abrahamson这只因为
    map
    是递归的,所以才有用。因此,
    go as
    map f as
    更有效。考虑到
    compose
    不是递归的,我看不出同样的概念如何应用于它。也有非递归的实例。我的观点是,内联线仅在定义中的所有变量都已填充时运行,因此在
    fx=\y->…
    fxy=…
    之间的行为不同,尽管它们在语义上是相同的。