«Базовые» значения могут использоваться только для вызова прямых вызовов в базовые реализации переопределенных членов

StackOverflow https://stackoverflow.com/questions/5847202

Вопрос

Почему я не могу позвонить 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top