Inheritance ';基数';值只能用于直接调用重写成员的基本实现

Inheritance ';基数';值只能用于直接调用重写成员的基本实现,inheritance,f#,overriding,base,derived,Inheritance,F#,Overriding,Base,Derived,为什么我不能在这里调用f的base实现: 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

为什么我不能在这里调用
f
base
实现:

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
更改为接受单个参数,则它将编译。大概这与curried参数和tupled参数有关,但是上面的代码在我看来很好。

您关于curried参数的假设是正确的。以下代码编译并正常运行:

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)

注意:我使用了元组参数。这个原因可能是因为在curried参数中,它将函数分解为多个函数(每个函数取一个参数)

我认为问题在于
base
不能通过闭包捕获-必须直接进行调用。但是,重写curried函数会自动创建闭包,因为只有第一个参数会立即应用。因此,尽管看起来您确实在使用
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

@kvb在他的分析中是正确的,但是如果你真的想覆盖一个curried方法,你可以。但语法相当冗长:

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

另见:(没有结论)。对我来说,这看起来像是一个编译器错误。我需要一些时间来理解你的答案,但既然你不是说这是一个编译器错误,那么我觉得逻辑上的结论是,既然我所尝试的基本上是惯用的,语言在这方面有缺陷。@jon-有这样一个误导性的错误信息可能是一个编译器错误。此外,没有基本限制阻止基成员从闭包中调用,尽管这不是一个需要解决的小问题。然而,我认为您的代码本质上不是惯用的。在模块中使用curried let绑定函数是惯用的,但使用curried成员并不惯用,正是因为这样的问题。就我个人而言,我不会用F#这样漂亮的函数式语言进行OO编程。如果你真的想做继承、基类等事情,那么就用C语言来做,因为在F语言中,OO神经元会觉得奇怪。F#首先是功能性的,让我们用它来实现only@Ankur:F#被吹捧为一种多范式语言,旨在支持OO和FP风格的编程。Curried成员通常是OOP语用学和FP语用学之间阻抗不匹配的地方之一。(混合F#和C#时会出现很多问题。)混合OOP和FP时,您必须同时设计两种范式,而不是两种范式中的任何一种。令人恼火,但随着使用,它确实变得更加自动化。