为什么 Haskell 强制数据构造函数的首字母大写?

发布于 2024-11-14 06:32:50 字数 623 浏览 1 评论 0原文

举一个丑陋的例子:

data Bighead = Big

little = 1 

f1 = little :: Int

f2 = Big :: BigHead

在我看来:

f1f2都指向一些数据。 (littleBig) 的唯一区别是 很少有一段代码可以做评估。但大没有。

它们都有一个可重写的主体,little可以从数据集合转换为结果,而Big只是不做最后一步——它总是保存这种数据形式(但可以递归地对它们进行求值)。

但在语法形式上,它们几乎是相同的:可以应用,可以评估。

一件大事可能是函数无法改变其应用的参数,但数据可以。

这是 Haskell 区别对待数据和函数名称的唯一原因吗?

需要分析:-)

编辑:更多的垫

data A = B Int

类型的B

B :: Int -> A

b :: Int -> A

b = B 

Give an ugly example:

data Bighead = Big

little = 1 

f1 = little :: Int

f2 = Big :: BigHead

In my opinion:

f1 and f2 all point to some data. the only different of (little and Big) is
little has a piece of code to do evaluation. but Big doesn't.

They all have a rewritable body, little can be transformed from a collection of data to a result, and Big is just don't do the last step --- it always holds this data forms (but recursively they can be evaluated).

But in syntax form, they are almost the same: can be applied, can be evaluated.

One big deal may be that functions can't alter its applied params, but data can do.

Is this the only reason that Haskell treats data and function's names differently?

Call for analysis :-)

edit: some more pads

data A = B Int

type of B:

B :: Int -> A

b :: Int -> A

b = B 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

长伴 2024-11-21 06:32:50

Haskell 98 语言 中,我们看到 Haskell 中标识符标记的核心区别:

varid   ->   (small {small | large | digit | ' })<reservedid>
conid   ->   large {small | large | digit | ' }

也就是说,语言从根本上来说是不同的在语言的所有级别(值和类型变量以及构造函数)区分变量名称(“varid”)和构造函数名称(“conid”)。很明显,Haskell 将标识符区分为两个主要名称空间(好吧,如果算上模块和类,还有其他名称空间),但有两个主要名称空间,即以小写字母开头的名称空间(变量标识符)和以大写字母开头的名称空间-大小写字母(构造函数标识符)。

因此,鉴于我们确实区分构造函数和变量,问题是“为什么?”。

读取类型

一个合理的论点是,它可以很容易地发现类型(例如多态类型)中的参数

模式匹配

其次,更重要的是,我们有统一的数据构造和解构语法(模式匹配)。每当您在模式中看到大写标识符时,

case x of
   Foo y z -> ...

就知道 Foo 是一个被分解的数据结构,并且其组件被命名。相应地,每当您在表达式中看到大写标识符时,

g (f (Foo 1 2)

就知道 f 正在接收带有两个参数的新建 Foo 数据类型。

因此,由于构造函数(类型和值)在语言中非常重要,这种对大写标识符的简单限制使人们更容易看到一段代码中发生了什么。在某些方面,大写字母弥补了语言中其他语法噪音的缺乏,作为对读者的帮助。


命名空间

Haskell 中有六种名称:变量和构造函数的名称表示值;类型变量、类型构造函数和类型类的那些引用与类型系统相关的实体;模块名称指的是模块。命名有两个限制:

变量和类型变量的名称是以小写字母或下划线开头的标识符;其他四种名称是以大写字母开头的标识符。
标识符不得用作同一范围内的类型构造函数和类的名称。
这些是唯一的限制;例如,Int 可能同时是单个作用域内的模块、类和构造函数的名称。

Haskell B

在 Haskell B 中,构造函数和变量可以使用任一情况。

From the Haskell 98 Language we see the core distinction in identifier tokens in Haskell:

varid   ->   (small {small | large | digit | ' })<reservedid>
conid   ->   large {small | large | digit | ' }

That is, the language fundamentally distinguish variable names ("varid") from constructor names ("conid"), at all levels of the language (both value and type variables and constructors). So clearly, Haskell distinguishes identifiers into two main namespaces (well, there are others, if you count modules and classes), but two primary ones, those that begin with a lower-case letter (variable identifiers) and those that begin with an upper-case letter (constructor identifiers).

So, given that we do distinguish constructors from variables, the question is "why?".

Reading types

One plausible argument is that it makes it very easy to spot parameters in types (e.g. polymorphic types).

Pattern matching

Secondly, and more importantly, we have uniform syntax for data construction and deconstruction (pattern matching). Whenever you see an upper case identifier in a pattern,

case x of
   Foo y z -> ...

You know that Foo is a data structure being taken apart and its components named. Correspondingly, whenever you see an upper case identifier in an expression,

g (f (Foo 1 2)

you know that f is receiving a newly built Foo data type with two arguments.

So, since constructors (both type and value) are so important in the language, this simple restriction to upper case identifiers makes it much easier for a human to see what is going on in a piece of code. In some ways upper case letters make up for the lack of other syntactic noise in the language, as an aid to the reader.


Namespaces

There are six kinds of names in Haskell : those for variables and constructors denote values; those for type variables, type constructors, and type classes refer to entities related to the type system; and module names refer to modules. There are two constraints on naming:

Names for variables and type variables are identifiers beginning with lowercase letters or underscore; the other four kinds of names are identifiers beginning with uppercase letters.
An identifier must not be used as the name of a type constructor and a class in the same scope.
These are the only constraints; for example, Int may simultaneously be the name of a module, class, and constructor within a single scope.

Haskell B

In Haskell B, constructors and variables could use either case.

饮惑 2024-11-21 06:32:50

构造函数名称在语法上需要与变量/函数名称不同,以区分模式匹配中的变量和构造函数。示例:

f (Foo bar) Baz bay = bar + bay

这里 Haskell 知道 FooBaz 是它应该匹配的构造函数,而 barbay 是它应该匹配的变量应该因为它们的大写方式而引入。

Constructor names need to be syntactically different from variable/function names to differentiate between variables and constructors in pattern matches. Example:

f (Foo bar) Baz bay = bar + bay

Here Haskell knows that Foo and Baz are constructors it should match against and bar and bay are variables it should introduce because of the way they are capitalized.

乄_柒ぐ汐 2024-11-21 06:32:50

除了已经提到的消除解析等歧义之外,还有
还有阅读程序的人类的可读性(和解析)。一些
支持报价:

程序必须编写供人阅读,并且只是顺便供机器执行。

--- Abelman 和 Sussman,计算机程序的结构和解释

任何傻瓜都可以编写计算机可以理解的代码。优秀的程序员编写人类可以理解的代码。

——马丁·福勒

In addition to disambiguating parsing etc., already mentioned, there's
also readability (and parsing) for humans reading the program. Some
supporting quotes:

Programs must be written for people to read, and only incidentally for machines to execute.

--- Abelman and Sussman, Structure and Interpretation of Computer Programs

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

--- Martin Fowler

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文