What am I missing: is function composition with multiple arguments possible?

最后都变了- 提交于 2019-12-21 07:58:06

问题


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?


回答1:


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.




回答2:


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 :)




回答3:


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)



来源:https://stackoverflow.com/questions/5446199/what-am-i-missing-is-function-composition-with-multiple-arguments-possible

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!