2011-03-18 183 views
7

任何人都可以向我解释数据/类型构造函数和函数之间有什么区别? Haskell将它们混合并给我们提供了一个通用界面(全部看起来像函数,特别是我们可以部分应用它们),而ML族语言区分它们。数据/类型构造函数和函数之间的区别?

+1

Haskell确实*不*具有“一切都是功能”的座右铭! http://conal.net/blog/posts/everything-is-a-function-in-haskell/ – sclv 2011-03-18 15:39:23

回答

16

你的二分法“Haskell vs. ML world”是错误的¹。 SML也促进了构造函数的功能,并且Caml Light曾经使用过。我不确定它为什么在OCaml中被删除,我认为设计者认为它没有真正的需要。

构造函数为什么稍微有些有深刻的原因。它们可以用于模式,而一般功能则不能 - 我想这可以用极化逻辑和聚焦来解释。另外,应用于值的构造函数可以被认为是一个值,而对于一般函数来说则不然。在按值调用的语言中,通常将递归值定义限制为允许构造函数应用程序的子类,但不允许使用通用函数应用程序。

我同意将所有构造函数提升为函数的“语义糖”很好。不过我认为,如果我们有一个很好的语法糖来进行短期抽象,比如斯卡拉的Some(_),那么这将不会很有用。 在我看来,构造函数是否应该是curryfied(你的“部分应用”评论)是一个不同的正交问题。

¹:除了是一个错误的二分法,你的问题的口气有一定的味道“Haskellers和MLers,这里是戒指,请打!”。它可能不是有意的,但无论如何你应该避免这样的表述。语言设计是作出妥协,并假设当两种不同的语言做出不同的选择时,其中一种是正确的而不是另一种不是好的方法。

PS:此问题已被编辑,现在更加中性。感谢您的编辑。




²:由petebu的要求,这里是一个多一点(其实很多更多)的 “聚焦和极性” 的信息。我想指出,我真的不是这个话题的专家(因此我猜“)。

我会首先推荐Neelakantan Krishnaswami在2009年发布的论文Focusing on Pattern Matching (PDF)。它包含一个不精通逻辑和聚焦(但至少需要熟悉后续微积分)的人的介绍。像往常一样,在连续微积分中,类型/命题被引入“在右边”并且在左边被消除/解构。但是在这里,我们用“极性”来分类类型,产品和总和是积极的并且功能是负的(我的直觉是产品/和数是数据,而函数是计算的,但是分离的动机来自对它们在连续微积分中行为的非常自然的考虑)并且论文显示左箭头类型的消除对应于函数应用,而和/产品类型的左消除对应于模式匹配。有一个case构造的行为与模式匹配类似(有一些差异),消除了积极因素,所以不能应用于函数。

Dan Licata,Noam Zeilberger和Robert Harper,2008年另一重要参考文献是Focusing on Binding and Computation(请注意,如果您打算提交关于这些主题的论文,“关注......”正在变得有点陈词滥调)。它更少强调与ML风格模式匹配的联系,但引入了一个非常好的想法,即虽然计算箭头在左边是“负值”(很容易看作经典等值A→B ≡ ¬A∨B),但可以引入一个不同的箭头,“正面的左“,因此是正极化的,可以是模式匹配的。事实证明,这个箭头非常适合表示变量绑定(如果您熟悉高阶抽象语法,则认为左边的极性排除了试图在变量上计算的“异国情调术语”),这样具有变量绑定的术语是可以像样式或产品那样进行模式匹配的数据结构。
我发现他们的纸有点难以阅读,所以我会从Dan Licata's slides开始。最后,罗伯特哈珀提出了other slides,提供了归纳判断/推导的不同直觉:正向箭头表示可衍生性(你可以在假设A和B?下建立C的推导),而负向箭头代表可接受性 (假设A和B的派生,你将如何重写/探索/操纵它们来构建C的派生?)。非常有趣的东西。

+0

+1为编号脚注 – phooji 2011-03-18 18:39:28

+0

+1。 “这可以用极化逻辑和聚焦来解释”。你能详细解释一下吗?链接到一篇论文可以做。 – petebu 2011-04-16 05:40:51

+0

@petebu:我编辑提供两个参考。 – gasche 2011-04-16 06:53:51

0

Haskell确实减少和简化了一些OCaml语法。但是Haskell语法确实可以区分构造函数和函数。函数以小写字母开头,构造函数以大写字母开头。使用中缀运算符数据构造函数必须以冒号开头,而普通运算符可能永远不会以冒号开头。

构造函数的接口可以看起来像简单的(也许是部分的)函数应用程序,这使得一个参数构造函数和大多数新类型非常易于使用(只是“你好”)。但Haskell确实允许使用OCaml类记录名称和{field = value,field = value}样式,但在Haskell中,您不必强制使用字段名称或强制使用此语法。因此,OCaml只为单个字段提供简单的语法,但Haskell允许您为多个字段使用简单的语法。最终,避免字段名称对于大型类型是不利的,因为类似位置函数的语法很难重构。

1

首先必须解释值和类型之间的差异。 “因为Haskell是纯粹的函数式语言,所有计算都是通过评估表达式(语法术语)来产生值(我们认为是答案的抽象实体),每个值都有一个关联的类型。 - Haskell 98的温和介绍(本教程不太温和)

Haskell的值是“first-class”,而Haskell的类型不是。类型用于描述值,而值和类型的关联称为键入。

数据/类型构造函数的区别在于:应用数据构造函数会产生一个值,但应用类型构造函数会产生一个类型。

函数只是描述值的表达式,它与一个类型相关联。当您评估函数时,您只是评估描述这些值的表达式。

+0

-1。我相信OP在询问代数数据类型构造函数和函数之间的差异,这两者都会产生值。 – petebu 2011-04-16 05:39:10

+1

@petebu我有相同的信念,但实际上OP是*非常*不明确,他的问题可以(正如我在阅读这个答案后意识到的)被解读为“为什么MLs在类型级别使用函数式语法像Haskell?“。我想最自然的答案是ML不支持模块语言之外的更高级别的类型,所以部分应用程序没有意义。 – gasche 2011-04-16 06:58:01

相关问题