我不确定我是否知道如何提出这个问题。在实现编译器时,我想允许客户端指定折叠元组。我提供了一种方法来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是微不足道的,那么为什么在语言中以一种好的方式这么做呢?]
答案 0 :(得分:2)
有两个组件合作导致此问题:
a * (b * c)
是同构的,但不等同于a * b * c
。结果是没有办法表达对任意长度的元组进行操作的函数的类型。
因此,简短的总结是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
部分中的注释只是一个提示这会带来什么。)
如果你想要实现的只是多重性,那么这个选项似乎有些过分。
免责声明:我对类型理论的了解有点过时了。