«Базовые» значения могут использоваться только для вызова прямых вызовов в базовые реализации переопределенных членов
-
27-10-2019 - |
Вопрос
Почему я не могу позвонить base
реализация f
здесь:
type Base =
abstract f : int -> int -> int
default this.f (x : int) (y : int) : int = x + y
type Derived =
inherit Base
override this.f (x : int) (y : int) : int = base.f -x -y
Призыв к base.f
Выдвигает эту ошибку компилятора:
error FS0419: 'base' values may only be used to make direct calls to the base implementations of overridden members
Если я изменюсь f
Чтобы взять один аргумент, он компилирует. Предположительно, это что -то связано с карри -параметрами по сравнению с параметрами, но приведенный выше код выглядит мне нормально.
Решение
Я считаю, что проблема в том, что base
не может быть захвачен закрытием - звонок должен быть сделан напрямую. Однако переопределение карри функции автоматически создает закрытие, поскольку только первый аргумент применяется немедленно. Следовательно, даже если похоже, что вы действительно используете base
значение, чтобы сделать прямой вызов базовой реализации переопределенного члена, вы фактически используете base
ценность в закрытии, что является незаконным.
К сожалению, я не думаю, что есть отличный способ обойти эту проблему. Как правило, вам следует избегать членов карри, когда это возможно, но вот одна альтернатива:
type Base =
abstract f : int -> (int -> int)
default this.f (x : int) = fun y -> x + y
type Derived =
inherit Base
override this.f x =
let fn = base.f -x
fun y -> fn -y
Другие советы
Ваше предположение о карри -параметрах верно. Приведенный ниже код компилирует и запускается нормально:
type Base () =
abstract f : int * int -> int
default this.f (x : int,y : int) : int = x + y
type Derived () =
inherit Base()
override this.f (x : int,y : int) : int =
base.f(-x,-y)
ПРИМЕЧАНИЕ. Я использовал параметры. Эта причина может быть связана с тем, что в карри -параметрах она разрушает функцию в нескольких функциях (каждая функция принимает 1 параметр)
@KVB прав в своем анализе, но если вы действительно хотите переопределить метод карри, вы можете. Синтаксис довольно многословный, хотя:
type Base =
abstract f : int -> (int -> int)
default this.f (x : int) = fun (y : int) -> x + y
type Derived =
inherit Base
override this.f (x : int) =
let baseCall = base.f -x
fun (y : int) -> baseCall -y