OCaml 中的管道运算符

问题描述 投票:0回答:1

在我使用 OCaml 编程的实践中,我最近发现以下管道运算符对于创建函数非常有用。

let (>|) f g x = g (f x)

val ( >| ) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c = <fun>

我用它来替换如下代码:

fun s -> int_of_string s |> Int.hash

 - : string -> int = <fun>

用更简单的方法:

int_of_string >| Int.hash

- : string -> int = <fun>

关联性很好:

int_of_string >| float_of_int >| string_of_float

- : string -> string = <fun>

这是否是对核心语言的有价值的改进?如果是,如何提交此贡献?

ocaml
1个回答
0
投票

这称为膏抹组合。在 Haskell 中,运算符是

.
,在 Elm 中是
>>
。这些在纯函数式语言中运行良好,但不幸的是,受到 OCaml 等允许多态性和副作用的语言的值限制的影响,因此不太可能被接受。

这个例子说明了问题:

let f x = x (* val f : 'a -> 'a *)
let g x = x (* val f : 'a -> 'a *)


let h = f >| g (* val h : '_weak3 -> 'weak3 *)
  
let a = h "foo"
let b = h 42 (* Error: This expression has type int but an expression was expected of type string *)

有关 OCaml 中的值限制和多态性限制的详细信息,请参阅OCaml 手册。但它的要点(据我理解)是,如果存在突变和多态混合的可能性,类型变量就不能完全泛化,将被weak类型变量取代,这可能在某些时候确定稍后一点,就像第一次使用时一样,但不能是多态的。不幸的是,出于组合函数的目的,这使其处理起来非常具有限制性和混乱性。

OCaml 确实稍微放宽了值限制,并且允许此类函数(如果它们是语法函数)。这意味着你可以做

let h s = (f >| g) s

但是你也不妨这样做

let h s = s |> f |> g

let h s = g @@ f s
© www.soinside.com 2019 - 2024. All rights reserved.