Scala和Frege(编程范式)之间的主要区别是什么?

时间:2013-07-28 05:33:44

标签: scala haskell functional-programming paradigms frege

Scala和Frege都是针对JVM的类型化函数语言。

Frege离Haskell更近,Scala有更独立的历史。

但是如果我们不看语法差异,那么两种允许的编程技巧,风格,概念有什么不同呢?

3 个答案:

答案 0 :(得分:41)

恕我直言,两者都是非常好的语言,但就范式而言,Scala比Frege更好OO,但Frege的功能优于Scala。关于差异,它主要归结为Haskell vs Scala,因为Frege(或几乎看到Haskell和Frege here之间的差异)Haskell用于JVM。

  1. Frege的类型推断是全局的,因此我们不必像在Scala(本地推断)中那样经常注释类型。

  2. 在Frege中,模块只是类型和函数的命名空间,而Scala有更好的模块系统。 http://2013.flatmap.no/spiewak.html

  3. 在Frege中,默认情况下函数是curry,因此不需要为部分函数应用程序添加其他构造。部分类型构造函数应用程序也是如此。

  4. 在弗雷格,没有def vs val,一切都是功能。因此,函数比Scala更加一流。

  5. Frege没有子类型,但类型系统会在本机调用中找出子类型。例如,您可以将ArrayList传递给需要Java List的函数。

    由于没有子类型,因此在Frege中我们现在无法扩展Java类或实现接口(将来可能会支持)所以我们需要一个可以扩展/实现的Java类,但方法实现将是从弗雷格作为职能部门传递。

  6. 从Scala开始,很容易调用Java,但在Frege中,必须在使用之前声明Java类/方法(只是类型和纯度注释)。例如,要使用Java的LinkedList

    data LinkedList a = native java.util.LinkedList where
        native add :: Mutable s (LinkedList a) -> a -> ST s Bool
        native get :: Mutable s (LinkedList a) -> Int -> ST s (Maybe a) throws
           IndexOutOfBoundsException
        native new :: () -> STMutable s (LinkedList a)
    

    由于这些函数会使对象变异,因此它们必须位于ST monad中。另请注意,此处Frege还处理null方法返回的get,因为它使用Maybe类型进行注释。 null通过本地接口的唯一方法是通过本地接口,因为Frege没有null的概念。

    另一个例子: pure native floor Math.floor :: Double -> Double

    表示该函数是纯函数,因此签名直接反映了没有IOST的原始Java签名。

  7. Frege没有Scala的var中的变量和副作用 通过类型更明确。 (只是没有null,没有var和明显的副作用使Frege更有趣,至少对我而言。从某种意义上说,Frege,就像Haskell一样,是一种“精细命令式编程语言”,适用于JVM !)

  8. 作为一个Haskell方言,Frege对Functors,Applicatives,Monads和其他功能“模式”更自然,并且有标准库中的那些,而在Scala中,你可能需要Scalaz。

  9. 默认情况下,Frege是惰性的,但必要时可以通过!启用严格性,而默认情况下Scala是严格的,但是对于延迟评估有lazy个关键字。

  10. 然而,作为JVM语言,一种语言可以从其他语言中受益。我曾经移植过Akka example to Frege。最后,它归结为严格性,纯度,功能,OO和类型推断以及它们对您有多重要。

答案 1 :(得分:17)

除了语法问题,最大的区别在于类型系统和执行模型。

正如@senia已经指出的那样,scala是严格的而不是纯粹的,这并不意味着你不能编写纯函数(你也可以在C中编写),只是编译器不会强制执行它。

Frege,OTOH是懒惰和纯粹的,这意味着所有不纯净的效果都被迫生活在ST或IO monad中。类型系统对于Haskell 2010至关重要,具有类型类和更高级别的函数类型。类型推断在程序范围内工作,唯一的例外是具有更高级别类型的函数,其中至少必须对多态参数进行注释。这是一个例子:

both f xs ys = (f xs, f ys)

对于此函数,编译器推断出类型:

both :: (α->β) -> α -> α -> (β, β)

请注意,由于xs的应用,ysf都具有相同的类型。 但现在假设我们想要使用多态列表函数,我们可以使用不同类型的xs和ys。例如,我们想写:

both reverse [1,2,3] ['a' .. 'z']

目前,这个应用程序会出错,因为这两个列表具有不同的元素类型,因此具有不同的类型。所以编译器会拒绝字符列表。

幸运的是,我们可以通过类型注释更准确地告诉编译器:

both :: (forall e.[e] -> [e]) -> [a] -> [b] -> ([a], [b])

这告诉我们:我们将向both传递一个函数,该函数执行一些列表转换但不关心列表元素类型。然后我们传递2个可能不同元素类型的列表。我们得到了一个包含我们转换后的列表的元组。 请注意,both的代码不需要更改。

实现同样目的的另一种方法是写:

both (f :: forall e.[e]->[e]) xs ys = (f xs, f ys)

并且类型检查器推断其余部分,即xsys必须是列表,但可以具有不同的元素类型。

Scalas类型系统完全(据我所知)支持OO。虽然Frege仅部分支持为Java导入的类型,但不支持定义类似OO的类型。

因此,两种语言都支持JVM环境中的函数式编程,尽管它们完全不同。第三个利基是动态类型的,其中Clojure是JVM世界中的王者。

答案 2 :(得分:3)

也许这不是主题,但Scala可以用来开发Android应用程序(*),但是Frege还没有被成功地用于那个。(**)IIRC,这是因为与现有Java库互操作要容易得多在斯卡拉比弗雷格,以及其他问题。

(*)警告。我自己只做过小的示例程序。

(**)Frege / Java混合已用于Android应用程序,但仅限Frege的应用程序仍无法使用,AFAIK。