imz*_*hev 32 paradigms haskell functional-programming scala frege
Scala和Frege都是针对JVM的类型化函数语言.
弗雷格更接近哈斯克尔,斯卡拉有更独立的历史.
但是如果我们不看语法差异,两者之间允许的编程技术,风格,概念有什么不同?
Mar*_*amy 41
恕我直言两者都是非常好的语言,但就范例而言,Scala比Frege更好OO,但Frege的功能比Scala更好.对于分歧,把它归结为主要的Haskell VS斯卡拉由于弗雷格是(或差不多,看到Haskell和弗雷格之间的差异在这里)为JVM哈斯克尔.
Frege的类型推断是全局的,因此我们不必像在Scala中那样频繁地注释类型(局部推理).
在Frege中,模块只是类型和函数的名称空间,而Scala具有更好的模块系统.http://2013.flatmap.no/spiewak.html
在Frege中,函数默认为curry,因此不需要为部分函数应用程序提供额外的构造.部分类型构造函数应用程序也是如此.
在弗雷格,没有defvs val,一切都是功能.因此,函数比Scala更加一流.
Frege没有子类型,但类型系统会在本机调用中找出子类型.例如,您可以将ArrayList一个函数传递给需要Java的函数List.
由于没有子类型,在Frege中我们现在无法扩展Java类或实现接口(将来可能会支持)所以我们需要一个可以扩展/实现的Java类,但方法实现将从Frege传递作为功能.
从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)
Run Code Online (Sandbox Code Playgroud)
这里因为函数改变了对象,所以它们必须是STmonad.另请注意,此处Frege还处理null从get方法返回的句柄,因为它是用Maybe类型注释的.唯一null可以通过本机接口进入Frege程序的方法是因为Frege没有null的概念.
另一个例子:
pure native floor Math.floor :: Double -> Double
其中声明该函数是纯函数,因此签名直接反映了原始Java签名而没有IO或ST.
弗雷格没有像Scala那样的变量,var副作用在类型上更明确.(只是没有null,没有var明确的副作用使Frege更有趣,至少对我来说.从某种意义上说,Frege,就像Haskell一样,是JVM的"优秀命令式编程语言"!)
作为Haskell方言,Frege对Functors,Applicatives,Monads和其他功能"模式"更自然,并且有标准库中的那些,而在Scala中,您可能需要Scalaz.
默认情况下,Frege是惰性的,但必要时可以启用严格性,!而Scala默认是严格的,但是有lazy懒惰评估的关键字.
然而,作为JVM语言,一种语言可以从其他语言中受益.我曾经把一个阿卡的例子移植到弗雷格.最后,它归结为严格性,纯度,功能,OO和类型推断以及它们对您有多重要.
Ing*_*ngo 17
除语法问题外,最大的区别在于类型系统和执行模型.
正如@senia已经指出的那样,scala是严格的而不是纯粹的,这并不意味着你不能编写纯函数(你也可以在C中编写),只是编译器不会强制执行它.
弗雷格,OTOH是懒惰和纯粹的,这意味着所有不纯的效果都被迫生活在ST或IO monad中.类型系统对于Haskell 2010至关重要,具有类型类和更高级别的函数类型.类型推断在程序范围内工作,唯一的例外是具有更高等级类型的函数,其中至少必须对多态参数进行注释.这是一个例子:
both f xs ys = (f xs, f ys)
Run Code Online (Sandbox Code Playgroud)
对于此函数,编译器推断类型:
both :: (?->?) -> ? -> ? -> (?, ?)
Run Code Online (Sandbox Code Playgroud)
请注意这两个xs和ys得到相同的类型,因为应用的f.但现在假设我们想要使用多态列表函数,我们可以使用不同类型的xs和ys.例如,我们想写:
both reverse [1,2,3] ['a' .. 'z']
Run Code Online (Sandbox Code Playgroud)
就目前而言,这个应用程序会出错,因为这两个列表具有不同的元素类型,因此具有不同的类型.所以编译器会拒绝字符列表.
幸运的是,我们可以通过类型注释更准确地告诉编译器我们想要的东西:
both :: (forall e.[e] -> [e]) -> [a] -> [b] -> ([a], [b])
Run Code Online (Sandbox Code Playgroud)
这告诉我们:我们将传递给both一个执行某些列表转换但不关心列表元素类型的函数.然后我们传递2个可能不同元素类型的列表.我们得到了一个包含我们转换后的列表的元组.请注意,代码both不需要更改.
实现同样目的的另一种方法是写:
both (f :: forall e.[e]->[e]) xs ys = (f xs, f ys)
Run Code Online (Sandbox Code Playgroud)
和类型检查推断的休息,即xs和ys必须列出,但可以有不同的元素类型.
Scalas类型系统完全(据我所知)支持OO.虽然Frege仅部分支持为Java导入的类型,但不支持自己的OO类型的定义.
因此,两种语言都支持JVM环境中的函数式编程,尽管它们完全不同.第三个利基是动态类型的,其中Clojure是JVM世界中的王者.
| 归档时间: |
|
| 查看次数: |
4817 次 |
| 最近记录: |