Optional parameters and option types using F#

梦想的初衷 提交于 2019-12-21 07:12:10

问题


Consider the following code:

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

While fn1 and fn2 work just fine, fn4 produces the following error:

init.fsx(6,30): error FS0001: This expression was expected to have type int but here has type 'a option

MSDN states:

Optional parameters are interpreted as the F# option type, so you can query them in the regular way that option types are queried, by using a match expression with Some and None.

To me, optional parameters are not interpreted as the F# option type otherwise the code would compile. Moreover I do not understand why, when I hover over ?bo in fn3 the tooltip says val bo: int option but from outside expects only int. I would expect a behavior of accepting nothing, int, Some int and None. And as the last note, I do not understand why fn2 works but fn4 does not.

Thanks for clarification


回答1:


I have to reconsider the correct answer. Based on this question (and answer):

Propagating optional arguments

it seams that the correct answer is the following:

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)

It is a neat feature and credits for the answer go to desco!




回答2:


  1. fn2 works because fn1 does not use its parameter, which is thus generic '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 complains that the parameter passed to fn3 should be an int, but not int option because when you specify the parameter, you of course need to pass in a specific one. But you have the option to omit the parameter. The definition/type signature of fn3 does not know whether you have specify bo or not, so it is a int option. Notice that you may have the following usage:

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

where you don't specify the parameter for fn3, but when you specify it, it is a concrete int, not int option.

Think about a plotting function with three parameters:

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

because the parameters are optional, you can have the following usage:

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

But not:

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


来源:https://stackoverflow.com/questions/6353897/optional-parameters-and-option-types-using-f

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