Необязательные параметры и типы параметров с использованием F # - PullRequest
13 голосов
/ 15 июня 2011

Рассмотрим следующий код:

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

Хотя fn1 и fn2 работают нормально, fn4 выдает следующую ошибку:

init.fsx (6,30): ошибка FS0001: ожидалось, что это выражение будет иметь тип int, но здесь имеет тип 'опция

MSDN состояния:

Необязательные параметры интерпретируются как тип опции F #, поэтому вы можете запрашивать их обычным образом, запрашивая типы опций, используя выражение соответствия с Some и None.

Для меня необязательные параметры не интерпретируются как тип опции F #, иначе код будет компилироваться.Более того, я не понимаю, почему при наведении курсора на ?bo в fn3 всплывающая подсказка говорит val bo: int option, но извне ожидает только int.Я ожидал бы поведения принятия ничего, int, Some int и None.И как последнее замечание, я не понимаю, почему fn2 работает, но fn4 не работает.

Спасибо за разъяснения

Ответы [ 2 ]

8 голосов
/ 18 августа 2011

Я должен пересмотреть правильный ответ.Основываясь на этом вопросе (и ответе):

Распространение необязательных аргументов

кажется, что правильный ответ следующий:

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 !

4 голосов
/ 15 июня 2011
  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 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')
...