Types ocaml%标识函数

Types ocaml%标识函数,types,ocaml,external,Types,Ocaml,External,我想知道为什么我们需要像“%identity”这样的函数,它与let a=a相同。它会通过使用它来提高性能吗 我在我的程序中引入了幻影类型,多次调用identity函数来转换类型,好奇“%identity”是否可以减少一些开销。identity函数是实现的一部分,而不是OCaml语言的一部分。它告诉编译器(本质上)将函数的参数更改为其返回值无需任何操作。换句话说,它告诉编译器继续使用相同的值,但改变其类型的概念。如果使用不当,它基本上会使OCaml类型系统的所有优秀安全保证失效。当然,它也不能保

我想知道为什么我们需要像“%identity”这样的函数,它与let a=a相同。它会通过使用它来提高性能吗


我在我的程序中引入了幻影类型,多次调用identity函数来转换类型,好奇“%identity”是否可以减少一些开销。

identity函数是实现的一部分,而不是OCaml语言的一部分。它告诉编译器(本质上)将函数的参数更改为其返回值无需任何操作。换句话说,它告诉编译器继续使用相同的值,但改变其类型的概念。如果使用不当,它基本上会使OCaml类型系统的所有优秀安全保证失效。当然,它也不能保证在该语言的任何其他实现(包括INRIA编译器的未来版本)中工作

OCaml编译器的内联功能应该已经保证不会为标识函数生成任何代码。所以我建议你继续使用它们

更新

在评论中回答一个无关的问题。。。。假设您有函数组合和标识函数:

let (<<) f g x = f (g x)
let id x = x
let(int=
#让合成l=List.fold_向右('a->'a=
示例:

# sum [2; 3; 5; 7];;
- : int = 17
# product [2; 4; 17];;
- : int = 136
# let mx = composition [(+) 1; ( * ) 10];;
val mx : int -> int = <fun>
# mx 2;;
- : int = 21
#sum[2;3;5;7];;
-:int=17
#产品[2;4;17];;
-:int=136
#设mx=composition[(+)1;(*)10];;
val mx:int->int=
#mx2;;
-:int=21

关键是0是加法的恒等式,1是乘法的恒等式,而
id
是函数组合的恒等式。
id
一直都很有用,就像0和1一样。

使用
%identity
作为外来原语可以并将减少与计算
相关的开销(乐趣x->x)
每次应用时关闭

OCaml编译器的特殊情况是
%
原语:
字节码/translcore.ml
将每个字节与一个特殊的内置AST节点相关联(在
%identity
的情况下,它被映射到
Pidentity
);编译器在节点上匹配并简化其应用于的表达式。对于本机编译器,相关行为:

  • asmcomp/closure.ml
    第197行和第19行:simplify
    %identity
    应用于常数参数本身:

    begin match p with
      Pidentity -> make_const_int x
    | Pnegint -> make_const_int (-x)
    
  • asmcomp/cmmgen.ml
    第1047行和ss.:将
    %identity
    简化为应用程序的LHS,以直接评估参数:

    match p with
      (* Generic operations *)
        Pidentity ->
          transl arg
    

字节码编译器对原语有类似的简化规则。

我们什么时候使用
identity
函数(不一定是
%identity
)通常情况下?这有点像问我们何时使用数字0和1。在函数为一级值的语言中,标识函数非常有用。对不起,我想我的问题应该是这样的,你能给我一个有用的例子,其中应该或必须使用
let f x=x
?(我添加了一个更新。我认为这实际上应该是一个单独的问题。)
match p with
  (* Generic operations *)
    Pidentity ->
      transl arg