我缺少什么:可以使用多个参数进行函数组合吗?

发布于 2024-10-27 08:28:00 字数 940 浏览 0 评论 0原文

我了解 F# 中函数组合的基础知识,例如 这里

不过,也许我错过了一些东西。 >><< 运算符似乎是在每个函数只接受一个参数的假设下定义的:

> (>>);;
val it : (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) = <fun:it@214-13>
> (<<);;
val it : (('a -> 'b) -> ('c -> 'a) -> 'c -> 'b) = <fun:it@215-14>

但是我想做什么,类似于以下内容:

let add a b = a + b
let double c = 2*c
let addAndDouble = add >> double   // bad!

但是,即使 add 的输出是 double 输入所需的类型,它也会被拒绝。

我知道我可以用一个元组参数重写 add:

let add (a,b) = a + b

或者我可以为第一个函数的每个可能参数编写一个新运算符:

let inline (>>+) f g x y = g (f x y)
let doubleAdd = add >>+ double

但这看起来很愚蠢!有我错过的更好的方法吗?

I understand the basics of function composition in F#, as, for example, described here.

Maybe I am missing something, though. The >> and << operators seem to have been defined with the assumption that each function only takes one argument:

> (>>);;
val it : (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) = <fun:it@214-13>
> (<<);;
val it : (('a -> 'b) -> ('c -> 'a) -> 'c -> 'b) = <fun:it@215-14>

What I'd like to do, however, is something like the following:

let add a b = a + b
let double c = 2*c
let addAndDouble = add >> double   // bad!

But even though add's output is of the type required for double's input, that is rejected.

I know that I can rewrite add with one tuple argument:

let add (a,b) = a + b

Or I can write a new operator for every number of possible arguments to the first function:

let inline (>>+) f g x y = g (f x y)
let doubleAdd = add >>+ double

But it seems silly! Is there a better way that I've missed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烟若柳尘 2024-11-03 08:28:00

您想要的并非完全不合理,但无法在 F# 的类型系统中指示广义组合运算符的类型。也就是说,没有好的方法来统一

(>>) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c

(>>+) : ('a -> 'b -> 'c) -> ('c -> 'd) -> 'a -> 'b -> 'd

(更不用说无限多个更高数量的版本)。因此,您别无选择,只能定义自己的附加运算符。在实践中,我经常发现以“尖头”风格编写的代码 let fxy = add xy |>无论如何,double 比无点/“无意义”let f = add (>>+) double 更具可读性。

What you want isn't totally unreasonable, but there would be no way to indicate the type of a generalized composition operator within F#'s type system. That is, there's no good way to unify

(>>) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c

and

(>>+) : ('a -> 'b -> 'c) -> ('c -> 'd) -> 'a -> 'b -> 'd

(not to mention the infinitely many higher arity versions). Therefore, you have no alternative but to define your own additional operators. In practice, I often find code written in the "pointed" style let f x y = add x y |> double more readable than the point-free/"pointless" let f = add (>>+) double anyway.

失去的东西太少 2024-11-03 08:28:00

查看您上面发布的 >><< 的类型。例如:

> (>>);;
val it : (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) = <fun:it@214-13>

它需要两个函数和一个值('a)并返回另一个值。您需要带有两个函数和两个值的东西。因此,>><< 都没有正确的类型签名。

你的实现一点也不傻。只是您的需求在 F# 库中并不是现成的。感谢您拥有一种允许您定义自己的运算符的语言,如下所示:)

Look at the types of >> and << that you posted above. eg:

> (>>);;
val it : (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) = <fun:it@214-13>

It takes two functions and a value ('a) and returns another value. You need something that takes two functions and 2 values. Hence, both >> and << don't have the correct type signature.

Your implementation isn't silly at all. It's just that your requirement doesn't come out of the box in F#'s libraries. Be thankful that you have a language which allows you to define your own operators like this :)

旧伤还要旧人安 2024-11-03 08:28:00

将一堆参数线程化怎么样?

let add = function x :: y :: t -> x + y :: t
let double = function x :: t -> 2 * x :: t

然后你可以编写任意数量的函数:

let doubleAdd = add >> double

它可以工作:(

> doubleAdd [7; 14]
42

另请参阅具有多个输入参数的F#函数组合)

How about threading a stack of arguments through?

let add = function x :: y :: t -> x + y :: t
let double = function x :: t -> 2 * x :: t

Then you can compose arbitrary arity functions:

let doubleAdd = add >> double

And it works:

> doubleAdd [7; 14]
42

(see also F# Function Composition with multiple input parameters)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文