Scala和Haskell类型系统有什么区别和相似之处? [英] What are the differences and similarities of Scala and Haskell type systems?

查看:105
本文介绍了Scala和Haskell类型系统有什么区别和相似之处?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何向Haskell专家解释Scala的类型系统?
Scala的优势是什么?

如何将Haskell的类型系统解释为高级的Scala执业者?
在Haskell中可以做什么不能在Scala中完成?

解决方案

Scala To a Haskell程序员:

Scala是一门严格且不纯的语言,具有一流的模块。数据类型被声明为具有细微差异的类或特征,模块或对象是这些类型的值。 Scala支持采用通用量化类型参数的类型构造函数。对象/类/特性具有由值,可变变量和函数(称为方法)组成的成员,模块作为变量隐式地传递给 this )。模块可能有类型成员,也可以带参数。类型成员存在量化,类型参数可以更高。因为类型可以是第一类值的成员,所以Scala提供了依赖类型的风格,称为 路径依赖类型



一流的函数也是模块。函数是一个名为 apply 的方法。一种方法不是一流的,但提供了一种语法来将方法包装在一等功能中。不幸的是,一个模块需要所有的类型参数,因此部分应用的一类函数不能被普遍量化。更一般地说,斯卡拉完全缺乏类型高于1的类型的直接机制,但可以利用更高类型的参数化模块来模拟rank-n类型。



Scala允许您声明任何给定类型的隐式值,而不是使用具有全局范围的类。这包括函数类型,它提供了隐式转换,因此也提供了类型扩展。除了隐式转换之外,类型扩展由扩展机制提供,它允许您在模块之间声明子类型/超类型关系。这种机制可以用来模拟代数数据类型,其中超类型可以看作数据声明左侧的类型,其子类型可以看作右侧的值构造函数。 Scala具有丰富的模式匹配功能,使用具有一流模式的虚拟化模式匹配器。

Scala支持子类型,这极大地限制了类型推断。但类型推断随着时间的推移而改善。支持较高kinded类型的推论。但是,斯卡拉缺乏任何有意义的类型系统,因此没有仁慈的推理和没有统一的东西。如果引入了一个类型变量,除非另有注释,否则它的类型是 * 。像 Any (所有类型的超类型)和 Nothing (每种类型的子类型)等特定类型在技术上都是<尽管它们不能用于类型参数。



Haskell给Scala程序员:



Haskell是一种纯粹的函数式语言。这意味着功能不允许有任何副作用。例如,Haskell程序不会按照这种方式打印到屏幕上,而是返回 IO [_] 数据类型的值的函数,它描述了一系列操作为了IO子系统的执行。



鉴于Scala在默认情况下是严格的,并为非严格函数参数提供by-name注释,所以Haskell在默认情况下使用by-需要语义,并为严格的参数提供注释。



Haskell中的类型推断比Scala中的类型推断更完整,它有完整的推理。这意味着类型注释几乎没有必要。



最近对GHC编译器的扩展允许在Scala中没有等价的高级类型系统特性,例如rank-n类型,类型族和类型多态性。

在Haskell中,模块是类型和函数的集合,但模块不是一流的实体。含义由类型类提供,但是这些属性在声明后是全局范围的,并且不能像Scala那样显式传递。通过用 newtype 包装来消除给定类型的多个类型类的实例以消除歧义,而在Scala中,只需通过作用域或显式传递实例即可解决。 / p>

由于Haskell不是面向对象的,所以没有方法/功能的二分法。每个函数都是第一类,每个函数默认都是curried(不是函数1,函数2等)。

Haskell没有子类型机制,但类型类可以有子类关系。


How to explain Scala's type system to a Haskell expert? What examples show Scala's advantages?

How to explain Haskell's type system to an advanced Scala practitioner? What can be done in Haskell that can't be done in Scala?

解决方案

Scala To a Haskell programmer:

Scala is a strict and impure language with first-class modules. Data types are declared as "classes" or "traits" with subtle differences, and modules or "objects" are values of those types. Scala supports type constructors taking universally quantified type parameters. Objects/classes/traits have members which consist of values, mutable variables, and functions (called "methods", to which the module is implicitly passed as a variable called this). Modules may have type members which can also take parameters. Type members are existentially quantified and type parameters can be higher-kinded. Because types can be members of first-class values, Scala provides a flavour of dependent typing called path-dependent types.

First-class functions are also modules. A function is a module with a method named apply. A method is not first-class, but a syntax is provided to wrap a method in a first-class function. Unfortunately, a module requires all of its type parameters up front, hence a partially applied first-class function is not allowed to be universally quantified. More generally, Scala completely lacks a direct mechanism for types of rank higher than 1, but modules parameterized on higher-kinded types can be exploited to simulate rank-n types.

Instead of type classes with global scope, Scala lets you declare an implicit value of any given type. This includes function types, which provides implicit conversion, and therefore type extension. In addition to implicit conversions, type extension is provided by the "extends" mechanism which lets you declare a subtype/supertype relation among modules. This mechanism can be used to simulate algebraic datatypes where the supertype can be seen as the type on the left-hand side of a data declaration, and its subtypes as the value constructors on the right-hand side. Scala has extensive pattern-matching capabilities using a virtualized pattern matcher with first-class patterns.

Scala supports subtyping, and this limits type inference considerably. But type inference has improved over time. Inference of higher kinded types is supported. However, Scala lacks any meaningful kind system, and therefore has no kind inference and no kind unification. If a type variable is introduced, it is of kind * unless annotated otherwise. Certain types like Any (the supertype of all types) and Nothing (a subtype of every type) are technically of every kind although they cannot be applied to type arguments.

Haskell to a Scala programmer:

Haskell is a purely functional language. This means that functions are not allowed to have any side-effects at all. For example, a Haskell program doesn't print to the screen as such, but is a function that returns a value of the IO[_] datatype which describes a sequence of actions for the IO subsystem to perform.

Whereas Scala is strict by default and provides "by-name" annotation for nonstrict function arguments, Haskell is lazy by default using "by-need" semantics, and provides annotation for strict arguments.

Type inference in Haskell is more complete than in Scala, having full inference. This means that type annotation is almost never necessary.

Recent extensions to the GHC compiler allow advanced type system features that have no equivalent in Scala, such as rank-n types, type families, and kinds polymorphism.

In Haskell, a module is a collection of types and functions, but modules are not first-class entities. Implicits are provided by type classes, but these are globally scoped once declared, and they cannot be passed explicitly as in Scala. Multiple instances of a type class for a given type are resolved by wrapping with a newtype to disambiguate, whereas in Scala this would be solved simply by scoping or by passing instances explicitly.

Since Haskell isn't "object-oriented", there's no method/function dichotomy. Every function is first class and every function is curried by default (no Function1, Function2, etc).

Haskell has no subtype mechanism, but type classes can have a subclass relationship.

这篇关于Scala和Haskell类型系统有什么区别和相似之处?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆