使用柯里化多次传递相同的参数链

Passing the same chain of parameters multiple times with currying

给出这个表达式:

// val fn1 : a:'a -> b:'b -> c:'c -> d:'d -> e:'e -> f:'f -> g:'g -> unit
// val fn2 : a:'a -> b:'b -> c:'c -> d:'d -> e:'e -> f:'f -> g:'g -> unit

type T =
  | A
  | B

// val t : T
// val a : 'a
// val b : 'b
// val c : 'c
// val d : 'd
// val e : 'e
// val f : 'f
// val g : 'g

match t with
| A -> fn1 a b c d e f g
| B -> fn2 a b c d e f g

有没有办法在调用支持柯里化的函数时不重复相同的参数链?所以你可以写一些像这样的奇怪的东西

(a, b, c, d, e, f, g)
|||||||> (match t with A -> fn1 | B -> fn2)

这是匿名记录的情况吗?实现这一目标的常见做法是什么?

只是申请,而不是管道?

(match t with
| A -> curried1
| B -> curried2
) 1 2 3 4

FSharp 闭包实现为 FSharpFunc<T, TResult>,它有一个 invoke 方法,让您无需多个部分应用程序即可调用该方法。

我不建议这样做,但在极端情况下,您可以使用反射来调用带有参数数组的函数。

let funInvoke fn args =
        let fnType = fn.GetType()
        if not (FSharpType.IsFunction fnType) then
            failwith "Not a function"

        let invoke = Array.head (fnType.GetMethods())
        invoke.Invoke(fn, args)

然后

funInvoke curried1 [|1; 2; 3 ; 4 |]

@Asti 的两种解决方案都可以正常工作。我会更进一步简化第一个。我更喜欢给事物命名,这样我就可以记住它们的意思,所以我会写:

let funcToCall = match t with | A -> curried1 | B -> curried2
funcToCall 1 2 3 4

但是,我认为评论中有一个有效的观点,即您的参数过多。在这种情况下,使用命名记录更有意义:

type FuncParams = { Doors:int; Windows:int; Walls:int; Chimneys:int; .... }

let arg = { Doors=1; Windows=2; Walls=3; Chimneys=4; ... }
match t with A -> curried1 arg | B -> curried2 arg