实现和表示polyadic操作

时间:2011-01-04 23:41:23

标签: ocaml

我不确定我是否知道如何提出这个问题。在实现编译器时,我想允许客户端指定折叠元组。我提供了一种方法来curry和uncurry一个函数,但这只是因为我在Ocaml中编写了一个二元运算符并将其折叠在术语和类型表示上。用户无法编写此功能。

在宏处理器中,用户可以编写此函数,因为元组是列表。

对于curried函数,用户可以轻松编写变换器,因为该术语在目标语言和术语的Ocaml表示以及输入中都是二进制的。

但他们不能为元组做这件事。这是另一个例子:用户可以轻松定义串行功能组合运算符。但用户无法定义并行组合:二进制版本:

 f1: D1 -> C1, f2: D2-> C2 --> f1 * f2: D1 * D2 -> C1 * C2

很容易写,但不能扩展到3个术语:这里折叠会计算

 f1 * (f2 * f3)

而不是

f1 * f2 * f3

[同构但不相等]

这个问题的概括是“我如何实现一种多语言编程语言”,这在这里要求太多了。我试图做的是提供内置变压器:

咖喱:T1 * T2 * T3 ...... - > T1 - > T2 - > ...    uncurry:T1 - > T2 - > .. T1 * T2 * T3

那么用户可以用二元运算符进行折叠:

uncurry (fold user_op (uncurry term))

但这既不够通用也不能很好..:)

我想Haskell的一个等价问题是:由于Haskell没有n-ary产品,n-ary元组构造函数在具有n个函数的库中进行模拟,其中每个函数必须手工写出。这显然很糟糕。如何解决这个问题?

[我的意思是,编写一个Python脚本来生成那些n个函数达到某个极限n是微不足道的,那么为什么在语言中以一种好的方式这么做呢?]

2 个答案:

答案 0 :(得分:2)

有两个组件合作导致此问题:

  • 元组不会自动展平 - 类型表达式中的括号不仅仅是组,它们会创建由其他元组连接的不同类型。这导致您观察到a * (b * c)是同构的,但不等同于a * b * c
  • 类型系统不提供在元组类型上表达代数的方法。我的意思是类型系统没有cons运算符或元组的任何等价物;没有办法表明某个类型的元组元素比其他类型更多或更少。

结果是没有办法表达对任意长度的元组进行操作的函数的类型。

因此,简短的总结是OCaml类型系统缺乏表达您尝试编写的函数类型的机制,因此您无法编写该函数(用Obj设置讨厌的游戏;您可以编写函数,但你不能用类型安全的方式表达它的类型。

答案 1 :(得分:0)

基本上有两种选择。

您可以使您的语言无类型或弱类型。例如,在C中,元组(整数,比如说)可以表示为int*。有些东西需要跟踪元组'长度,但类型系统不会。我假设你不想那样走。

对于类型安全的语言,您需要一个非常富有表现力的类型系统。也就是说,您需要依赖于值的类型。其成员是返回类型的函数。例如,元组类型构造函数(不要与元组构造函数混淆)可以具有类型tuple : int -> Type -> Type。 扩展元组的操作可以具有类型forall n:int. forall T:Type. tuple n T -> T -> tuple (n+1) T。这样的类型系统是有代价的:通常,类型推断不是递归的,如果你愿意用它们的类型注释所有类型的子表达式,那么类型检查只是可判定的(上面forall部分中的注释只是一个提示这会带来什么。) 如果你想要实现的只是多重性,那么这个选项似乎有些过分。

免责声明:我对类型理论的了解有点过时了。