【问题标题】:Optional parameters and option types using F#使用 F# 的可选参数和选项类型
【发布时间】:2011-09-15 06:48:03
【问题描述】:

考虑以下代码:

type Test () =
  member o.fn1 (?bo) = 1
  member o.fn2 (?bo) = o.fn1 bo

  member o.fn3 (?bo) = 1 + bo.Value
  member o.fn4 (?bo) = o.fn3 bo

虽然fn1fn2 工作正常,但fn4 会产生以下错误:

init.fsx(6,30):错误 FS0001:此表达式应为 int 类型,但此处的类型为 'a option

MSDN 状态:

可选参数被解释为 F# 选项类型,因此您可以使用带有 Some 和 None 的匹配表达式以查询选项类型的常规方式查询它们。

对我来说,可选参数不会被解释为 F# 选项类型,否则代码会编译。此外,我不明白为什么,当我将鼠标悬停在fn3 中的?bo 上时,工具提示会显示val bo: int option,但从外部只需要int。我希望一种不接受任何东西的行为,int,Some int 和 None。最后一点,我不明白为什么fn2 有效,而fn4 无效。

感谢您的澄清

【问题讨论】:

    标签: f# types option optional-parameters


    【解决方案1】:

    我必须重新考虑正确答案。基于这个问题(和答案):

    Propagating optional arguments

    似乎正确答案如下:

    type Test () =
      member o.fn1 (?bo) = 1
      member o.fn2 (?bo) = o.fn1 bo
    
      member o.fn3 (?bo) = 1 + bo.Value
      member o.fn4 (?bo) = o.fn3 (?bo = bo)
    

    这是一个简洁的功能,答案归功于desco

    【讨论】:

      【解决方案2】:
      1. fn2 起作用是因为fn1 不使用它的参数,因此它是通用的'b option

        type Test () =
           member o.fn1 (?bo1) = 1  --> bo1: 'b option, here 'b = 'a option
           member o.fn2 (?bo) = o.fn1 bo  -->bo: 'a option
        
      2. fn4 抱怨传递给fn3 的参数应该是一个int,而不是int option,因为当你指定参数时,你当然需要传入一个特定的。但是您可以选择省略参数。 fn3 的定义/类型签名不知道你是否指定了bo,所以它是一个int option。请注意,您可能有以下用法:

        type Test () =
           member o.fn1 (?bo) = 1
           member o.fn2 (?bo) = o.fn1 bo
        
           member o.fn3 (?bo) = 
           match bo with
             | Some v -> 1 + bo.Value
             | None -> 1
        
           member o.fn4 (?bo) = o.fn3()
        

      你没有为fn3指定参数,但是当你指定它时,它是一个具体的int,而不是int option

      考虑一个具有三个参数的绘图函数:

      let plot(?x,?y,?color)
      

      因为参数是可选的,所以可以有如下用法:

      plot(data)
      plot(y=data)
      plot(x=data, color='r')
      

      但不是:

      plot(Some data)
      plot(y=Some data)
      plot(x=Some data, color=Some 'r')
      

      【讨论】:

      • 我得到了你的评论,但我仍然不喜欢它的完成方式。我更希望能够发送nothing, value, Some value and None。当我想将可选参数从一个成员重新发送到另一个成员时,我必须在第一个成员中对其进行模式匹配,并在有和没有参数的情况下调用第二个成员,或者我必须定义另一个具有选项类型的成员并将所有成员重新发送给这个成员。
      • 可选参数是一种对库用户友好的语法,但对库作者不友好。您站在图书馆作者的立场来判断此功能。接口越动态,对底层实现的检查就越多。
      【解决方案3】:

      F# 不需要匹配来传递可选参数。 使用情节示例:

      type Plotter() =
          static member Plot(?x,?y,?color) = 
              printfn $"{x}, {y}, {color}" // Do something "plottish" here
      
      type PlotUser() =
          static member MyPlotUser(?x, ?y, ?color) =
              Plotter.Plot(?x = x, ?y = y, ?color = color)
      
      /// Perform calls
      PlotUser.MyPlotUser(10) // => Some(10), , 
      PlotUser.MyPlotUser(10, color = "Green") // => Some(10), , Some(Green)
      
      

      上面允许您使用自己的可选参数调用 plot。 /JEE,夏普#Soft

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-17
        • 2023-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多