【问题标题】:Why cannot f# function with curried arguments have optional parameter [duplicate]为什么带有咖喱参数的f#函数不能有可选参数[重复]
【发布时间】:2026-01-04 02:20:02
【问题描述】:

好的,我对 F# 很陌生,所以这可能在教科书中得到了很好的解释,但是为什么带有柯里化参数的 F# 函数不能有可选参数。例如函数Fun1 不能编译,而其他两个函数编译得很好。我想知道对可选参数有这个限制的原因是什么?有没有办法绕过这个限制?

type TestOptionalParameter = 
    member x.Fun1 (a: int) (?b : bool) = 
        if defaultArg b true then a else 2 * a
    member x.Fun2 (?b : bool) = 
        if defaultArg b true then "yes" else "no"
    member x.Fun3 (a: int, ?b : bool) = 
        if defaultArg b true then a else 2 * a

【问题讨论】:

    标签: f#


    【解决方案1】:

    让我们看一个例子是否允许:

    let top = TestOptionalParameter()
    let fn1 = top.Fun1 4
    

    在这种情况下,fn1 的值是:(bool -> int) 类型的 函数 或具有默认第二个参数值 (@ 987654324@)?

    我认为由于这种歧义,带有柯里化参数的函数不允许有可选参数

    【讨论】:

      【解决方案2】:

      我猜这是在 F# 中做出的设计决定,因为在 OCaml 的柯里化函数中可以有可选参数。

      F# 中的可选参数是通过选项类型实现的,假设你有一个(例如)int -> bool option -> int 的函数,即使你对可选参数版本有一些特殊的注解,例如int -> ?bool -> int 我认为推理这些函数在实际使用中的行为可能会变得更加困难,尤其是在存在部分应用的情况下,因为参数的数量并不总是与类型签名所暗示的相匹配。

      关于在 OCaml 中实现的这种方法的一些缺点,您可能会对这个答案感兴趣:https://*.com/a/23703761/5438433

      在 F# 语言设计用户语音站点上的 let 绑定函数中实现可选参数的建议:https://fslang.uservoice.com/forums/245727-f-language/suggestions/5663215-optional-and-named-parameters-on-let-bindings-on-m,我不清楚如果接受,这是否会实现与当前可用的相同的行为类型上的可选参数或为 curried 参数实现类似 OCaml 的行为。

      【讨论】:

      • 在所有关于这个问题的答案中,我特别喜欢这个,因为它不仅仅是简单地回答问题。