Scala与F#问题:它们如何统一OO和FP范式?

Scala与F#问题:它们如何统一OO和FP范式?,scala,f#,functional-programming,comparison,paradigms,Scala,F#,Functional Programming,Comparison,Paradigms,Scala和F#采用的统一OO和FP范式的方法之间的关键区别是什么 编辑 每种方法的相对优缺点是什么?如果,尽管支持子类型,F#可以推断函数参数的类型,那么为什么Scala不能呢?F#是功能性的-它很好地支持OO,但设计和原理仍然是功能性的。示例: Haskell型函数 自动咖喱 自动泛型 参数的类型推断 以主要面向对象的方式使用F#感觉比较笨拙,因此可以将其主要目标描述为将OO集成到函数式编程中 Scala是一种注重灵活性的多范式。您可以根据当前最适合的方式在真实的FP、OOP和过程风格之

Scala和F#采用的统一OO和FP范式的方法之间的关键区别是什么

编辑

每种方法的相对优缺点是什么?如果,尽管支持子类型,F#可以推断函数参数的类型,那么为什么Scala不能呢?

F#是功能性的-它很好地支持OO,但设计和原理仍然是功能性的。示例:

  • Haskell型函数
  • 自动咖喱
  • 自动泛型
  • 参数的类型推断
以主要面向对象的方式使用F#感觉比较笨拙,因此可以将其主要目标描述为将OO集成到函数式编程中

Scala是一种注重灵活性的多范式。您可以根据当前最适合的方式在真实的FP、OOP和过程风格之间进行选择。它实际上是关于统一OO和函数式编程。

F#的语法取自OCaml,但F#的对象模型取自.NET。这为F#提供了一种简洁明了的语法,这是函数式编程语言的特点,同时允许F#通过其对象模型非常顺利地与现有的.NET语言和.NET库进行互操作


Scala在JVM上的工作与F在CLR上的工作类似。然而Scala选择采用更类似Java的语法。这可能有助于面向对象程序员采用它,但对于函数式程序员来说,它可能会感到有点沉重。它的对象模型类似于Java,允许与Java无缝互操作,但有一些有趣的区别,比如对traits的支持。

有很多要点可以用来比较两者(或三者)。首先,我可以想到以下几点:

  • 语法
    在语法上,F#OCaml基于函数式编程传统(空间分隔且更轻量级),而Scala基于面向对象风格(尽管Scala使其更轻量级)

  • 集成OO和FP
    F#Scala都非常顺利地将OO与FP集成在一起(因为这两者之间没有矛盾!!)您可以声明类来保存不变的数据(功能方面),并提供与数据相关的成员,还可以使用接口进行抽象(面向对象方面)。我对OCaml不太熟悉,但我认为它更强调OO方面(与F#相比)

  • F#中的编程风格
    我认为F#中通常使用的编程风格(如果您不需要编写.NET库并且没有其他限制)可能更实用,并且您只会在需要时使用OO特性。这意味着您可以使用函数、模块和代数数据类型对功能进行分组

  • Scala中的编程风格
    在Scala中,默认的编程风格更面向对象(在组织中),但是您仍然(可能)编写功能性程序,因为“标准”方法是编写避免变异的代码


如果函数编程意味着使用函数编程,那么Scala会稍微改变这一点。在Scala中,如果我理解正确的话,您使用的是方法而不是函数编程

当方法背后的类(以及该类的对象)无关紧要时,Scala会让您假装它只是一个函数。也许Scala语言律师可以详细说明这种区别(如果它是一种区别的话)以及任何后果。

我已经看过F#,做过低级教程,所以我对它的了解非常有限。然而,很明显,它的风格本质上是功能性的,OO更像是一个附加组件——更像是ADT+模块系统,而不是真正的OO。我得到的感觉可以最好地描述为它中的所有方法都是静态的(就像在JavaStatic中一样)

例如,请参见使用管道操作符的任何代码(
|>
)。请从以下站点获取此代码段:

函数
map
不是列表实例的方法。相反,它的工作方式类似于
列表
模块上的静态方法,该模块将列表实例作为其参数之一

另一方面,Scala完全是面向对象的。首先,让我们从该代码的Scala等价物开始:

List(1 to 10) map fib

// Without operator notation or implicits:
List.apply(Predef.intWrapper(1).to(10)).map(fib)
这里,
map
List
实例上的一个方法。类似于静态的方法,例如
Predef
上的
intWrapper
List
上的
apply
,要少见得多。还有一些函数,如上面的
fib
。这里,
fib
不是
int
上的方法,但也不是静态方法。相反,它是一个对象——我看到F#和Scala之间的第二个主要区别

让我们考虑来自维基百科的F~*实现,以及等价的Scala实现:

// F#, from the wiki
let rec fib n =
    match n with
    | 0 | 1 -> n
    | _ -> fib (n - 1) + fib (n - 2)

// Scala equivalent
def fib(n: Int): Int = n match {
  case 0 | 1 => n
  case _ => fib(n - 1) + fib(n - 2)
}
上面的Scala实现是一种方法,但Scala将其转换为一个函数,以便能够将其传递给
map
。我将在下面对其进行修改,使其成为一个返回函数的方法,以显示函数在Scala中的工作方式

// F#, returning a lambda, as suggested in the comments
let rec fib = function 
    | 0 | 1 as n -> n 
    | n -> fib (n - 1) + fib (n - 2)

// Scala method returning a function
def fib: Int => Int = {
  case n @ (0 | 1) => n
  case n => fib(n - 1) + fib(n - 2)
}

// Same thing without syntactic sugar:
def fib = new Function1[Int, Int] {
  def apply(param0: Int): Int = param0 match {
    case n @ (0 | 1) => n
    case n => fib.apply(n - 1) + fib.apply(n - 2)
  }
}
因此,在Scala中,所有函数都是实现trait
FunctionX
的对象,它定义了一个名为
apply
的方法。如这里所示,在上面的列表创建中,
.apply
可以省略,这使得函数调用看起来就像方法调用一样

最后,Scala中的所有东西都是一个对象——一个类的实例——每个这样的对象都属于一个类,所有代码都属于一个方法,该方法以某种方式执行。在上面的例子中,甚至
match
也曾是一个方法,但已被转换为关键字
// F#, returning a lambda, as suggested in the comments
let rec fib = function 
    | 0 | 1 as n -> n 
    | n -> fib (n - 1) + fib (n - 2)

// Scala method returning a function
def fib: Int => Int = {
  case n @ (0 | 1) => n
  case n => fib(n - 1) + fib(n - 2)
}

// Same thing without syntactic sugar:
def fib = new Function1[Int, Int] {
  def apply(param0: Int): Int = param0 match {
    case n @ (0 | 1) => n
    case n => fib.apply(n - 1) + fib.apply(n - 2)
  }
}