Function OCaml中的函数包装器/装饰器

Function OCaml中的函数包装器/装饰器,function,ocaml,wrapper,Function,Ocaml,Wrapper,我有一个具有以下签名的函数: val func : a -> b -> c -> d -> e -> f -> unit 有时也会引发例外。我想更改控制流,使其看起来像这样: val funcw : a -> b -> c -> d -> e -> f -> [ `Error of string | `Ok of unit ] let w1 f x = try `Ok (f x) with e -> `Error

我有一个具有以下签名的函数:

val func : a -> b -> c -> d -> e -> f -> unit
有时也会引发例外。我想更改控制流,使其看起来像这样:

val funcw : a -> b -> c -> d -> e -> f -> [ `Error of string | `Ok of unit ]
let w1 f x = try `Ok (f x) with e -> `Error (Printexc.to_string e)
let ws f x y =
    match f x with
    | `Ok f' -> (try `Ok (f' y) with e -> `Error (Printexc.to_string e))
    | `Error _ as err -> err
let w2 f = ws (w1 f)
let w3 f x = ws (w2 f x)
let w4 f x y = ws (w3 f x y)
let w5 f x y z = ws (w4 f x y z)
let w6 f x y z w = ws (w5 f x y z w)

我尝试包装它的方式很难看:制作另一个函数,
funcw
,它接受相同数量的参数,对它们应用
func
,并使用
尝试
/
。但肯定有比这更好的办法。想法?

您可以将
f
作为包装器函数的一个参数。这更一般一点

let w6 f a b c d e g =
    try `Ok (f a b c d e g) with e -> `Error (Printexc.to_string e)
然后,
func
的包装版本是
(w6 func)

此包装器适用于6个参数的curried函数,如
func
。您不能为所有不同数量的参数定义一个包装器(因为它们有不同的类型),但您可以为不同数量的参数定义一系列包装器,如下所示:

val funcw : a -> b -> c -> d -> e -> f -> [ `Error of string | `Ok of unit ]
let w1 f x = try `Ok (f x) with e -> `Error (Printexc.to_string e)
let ws f x y =
    match f x with
    | `Ok f' -> (try `Ok (f' y) with e -> `Error (Printexc.to_string e))
    | `Error _ as err -> err
let w2 f = ws (w1 f)
let w3 f x = ws (w2 f x)
let w4 f x y = ws (w3 f x y)
let w5 f x y z = ws (w4 f x y z)
let w6 f x y z w = ws (w5 f x y z w)

可能会有一个更整洁的方案,但这看起来相当不错。

对不起,我意识到我有两个
f
s(一个是函数,一个是类型)。更改为
func
funcw
。我宁愿避免这种解决方案,因为它消除了参数
func
所采用的单一真理点。FWIW类型和值占用不同的名称空间。您可以有一个名为f的函数和一个名为f的类型。我最终在我们使用的库中找到了一个应用程序函子shim。看看是否好奇。谢谢你的帮助!