Functional programming 使用currying多次传递同一参数链

Functional programming 使用currying多次传递同一参数链,functional-programming,f#,currying,Functional Programming,F#,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 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
在调用支持curry的函数时,有没有办法不重复相同的参数链?所以你可以写一些像这样奇怪的东西

(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
,它有一个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

如果你的函数有10个参数,你可能会错过some@FyodorSoikin哦,那太令人困惑了,对不起!我添加了一些签名。为了可读性,我会做
let f=match,然后一次
f a b c d e
。或者围绕它进行排列并应用(如第一个答案所示)。如果您在多个函数上有相同的参数集,请创建一个记录、一个类型别名或一个大小写DU以获得更清晰的代码。就是这样!当时的命名现在起作用了。最终我将创建一个记录,但现在我正处于一个难闻的阶段,试图找出如何处理所有这些参数传递。谢谢各位