内部如何定义 (,)?

6

重新定义这个函数很容易

(,) :: a -> b -> (a,b)
(,) a b = (a,b)

奇怪的是,这个函数可以用于任意长度的元组。比如说,实际上有一个函数:

(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) :: a -> b -> c -> ... -> (a,b,c,...)

这是如何实现的?为什么不对元组的所有标准函数(如zip)进行此操作?
Hoogle给我没有结果,我也看不出模板Haskell如何做到这一点,所以我认为这必须是编译器内部的某种魔法。但这对我来说似乎非常不符合Haskell的风格。

1
你现在应该已经收到你的问题了。 - Brad Larson
3个回答

5

这是如何实现的?

编译器支持。Haskell 语言报告规定 (,) 至少支持最多 15 个参数(6.1.4),但 GHC 更进一步,可以生成更多的参数(上次我们测试时可以处理数百甚至数千个)。zip 和其他元组函数必须定义为多达 7 元组。我不知道 GHC 是否会为更大的数量生成它们。


1
“数百甚至数千” <- 真的吗?当我尝试时, GHC 7.4.1 报告 63 元组对于 GHC 来说太大了(最大大小为 62)解决方法:使用嵌套元组或定义数据类型 - Daniel Wagner
为什么是62?64(2的6次方)会更有意义。有人知道多出来的2去哪了吗? - Mike Izbicki
2
类型检查器在某些情况下具有指数时间复杂度。因此,一些类别不能为长元组定义,详见 ghc-prim 中的 GHC.Tuple 源代码。 - permeakra
1
@DanielWagner 当我在ghci中执行:t (,,,,,,,,,,,,,,,,,,,,, ...)时,即使是在ghc 7.4.1下,我也可以将其至少提高到2000而不会出现任何问题。 - Mike Izbicki
是的,我们只是查看它是否能够生成(,,,,...),而不是用它构建实际的元组。 - Cat Plus Plus
@MikeIzbicki 嗯,有趣。似乎 GHC 直到你尝试将其实际应用于某些东西才会抱怨。例如,let y = (,,...) 0 已经足以让它抱怨了。 - Daniel Wagner

1
我的理解是(,)不是一个常规函数,它是一种具有特殊语法的构造函数,被硬编码到语言中。它类似于语法[1, 2, 3],你无法定义它,因为它是硬编码的。

1

这在语言定义中被指定并硬编码到编译器中。在Haskell中,您不需要定义元组,因为Haskell的定义已经包括了元组。

对于元组(匿名产品类型),有一种被广泛接受的(,,,)语法,它们是相当基本的。由于每个组件都存在且可以被推断,因此它们也可以很好地与类型推断配合使用。

目前还没有被广泛接受的匿名和类型的语法,它们可能无法很好地与类型推断配合使用。

Haskell提供了用户可定义的中缀语法,但不提供用户可定义的括号(除了广泛的准引用可能性)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接