Haskell元组构造函数(GHC)和语言及其实现之间的分离

The*_*kle 35 haskell functional-programming tuples comma ghc

当我意识到这一点时,哈斯克尔再次震惊了我的思绪

(x,y)
Run Code Online (Sandbox Code Playgroud)

只是语法糖

(,) x y
Run Code Online (Sandbox Code Playgroud)

当然我想把它扩展到更大的元组.但

(,) x ((,) y z)
Run Code Online (Sandbox Code Playgroud)

给我

(x,(y,z))
Run Code Online (Sandbox Code Playgroud)

这不是我想要的.一时兴起,我试过了

(,,) x y z
Run Code Online (Sandbox Code Playgroud)

它有效,给出我想要的东西:

(x,y,z)
Run Code Online (Sandbox Code Playgroud)

这提出了一个问题:你能走多远?令我惊讶的是,似乎没有任何限制.以下所有都是有效的运营商:

(,)
(,,)
(,,,)
(,,,,)
--etc
(,,,,,,,,,,,,,,)
(,,,,,,,,,,,,,,,)
--etc
(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)
--etc
Run Code Online (Sandbox Code Playgroud)

这种行为是惊人的,并导致我的实际问题:它是否可以在我自己的功能中模拟?或者它只是元组运算符的GHC特定功能?我认为它是后者,因为我已经阅读了haskell98规范和iirc它说实现只需要为最多15个项目定义元组运算符.而GHC已经全力以赴,让你可以达到任意限制.

那么,是否可以在haskell实现本身中定义这个运算符/函数族,只使用类型系统和现有语言特性(声明,类型签名,函数定义等)?如果是这样,怎么样?或者这是不可能的,你必须考虑编译器来找到这个函数集合的支持框架?

这导致了一个更普遍的问题:Haskell本身支持多少Haskell,通过类型和函数定义,声明等; 以及编译器/实现支持多少?(我知道GHC是用Haskell编写的,但没有回答这个问题)

也就是说,如果你放弃标准库(包括前奏)并在原始的Haskell中从头开始做所有事情; 是否可以使用GHC的所有功能构建一个完整的实现,只使用最少的一组功能?为了使用Haskell构建haskell实现,您需要哪些最小的语言功能集?我是否可以放弃前奏,然后在GHC内手动完全重建?如果你放弃了前奏而从不导入任何东西,你还有什么可以继续使用?

看起来好像我问了一百万个问题,但他们真的都试图用不同的措辞问同样的问题.给你最好的拍摄!

C. *_*ann 38

唉,元组中没有魔法.这是GHC使用的实现,并让您了解这里发生了什么是最后一个定义的来源:

data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__
  = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__
Run Code Online (Sandbox Code Playgroud)

...是啊.

那么,是否可以在haskell实现本身中定义这个运算符/函数族,只使用类型系统和现有语言特性(声明,类型签名,函数定义等)?如果是这样,怎么样?或者这是不可能的,你必须考虑编译器来找到这个函数集合的支持框架?

不,没有办法以通用方式定义这样的元组.常见的模式纯粹是语法,没有什么可以在类型系统或其他方面递归地完成.当然,您可以使用Template Haskell生成此类定义,但您仍然会使用字符串操作单独生成每个定义以创建名称,而不是使用任何类型的共享结构.

还有一个问题是元组语法是内置的,而不是可以模仿的东西,但这是一个单独的问题.你可以想象类似的类型:

data Tuple2 a b = Tuple2 a b
data Tuple3 a b c = Tuple3 a b c
Run Code Online (Sandbox Code Playgroud)

......等等,它们不使用特殊语法,但由于上述原因仍然无法定义.

这导致了一个更普遍的问题:Haskell本身支持多少Haskell,通过类型和函数定义,声明等; 以及编译器/实现支持多少?(我知道GHC是用Haskell编写的,但没有回答这个问题)

几乎所有这些都是在Haskell中定义的.某些东西具有你无法模仿的特殊语法,但在大多数情况下只会扩展到编译器特别关注某些定义.否则,有没有什么区别:

data [] a = [] | a : [a]
Run Code Online (Sandbox Code Playgroud)

......以及您自己定义的任何等效类型.

也就是说,如果你放弃标准库(包括前奏)并在原始的Haskell中从头开始做所有事情; 是否可以使用GHC的所有功能构建一个完整的实现,只使用最少的一组功能?为了使用Haskell构建haskell实现,您需要哪些最小的语言功能集?我是否可以放弃前奏,然后在GHC内手动完全重建?如果你放弃了前奏而从不导入任何东西,你还有什么可以继续使用?

您可能会发现阅读有关GHC的NoImplicitPrelude和RebindableSyntax扩展的启发,这些扩展可以让您更改用于解释do符号的定义,如何处理数字文字,if then else语法的作用等等.

我只想说非常,非常少,无法重新实现.大多数事情只能由于语法而变得特殊,并且可以替换为等效的东西(如上面的列表和元组).

最后,有一组有限的东西具有非常特殊的行为 - IO类型是一个明显的例子 - 根本不能替换,因为它们直接挂在运行时系统中的某些东西上,你不能更换.

  • 更忠实的选择是`data Tup ab = Tup a!b`,然后`type Pair ab = Tup a(Tup b()); 类型Triple abc = Tup a(Tup b(Tup c()))`如果你也可以让编译器解压缩`Tup`中的strict b,那么表示就像元组一样. (4认同)