这是一个一直困扰着我的问题,我想知道这里是否有人可以提供帮助。
我有一个名为lambdaLVar的PLT Redex模型,它或多或少是一个花园种类的无类型lambda演算,但扩展了包含“格子变量”或LVars的商店。 LVar是一个变量,其值只能随时间增加,其中“增加”的含义由语言用户指定的部分有序集(也称为格子)给出。因此lambdaLVar实际上是一个语言系列 - 用一个格子实例化它,你得到一种语言;有一个不同的格子,你得到另一个。您可以查看代码here;重要的是lambdaLVar.rkt。
在lambdaLVar的纸上定义中,语言定义由用户指定的晶格参数化。很长一段时间,我想在Redex模型中进行相同类型的参数化,但到目前为止,我还没弄清楚如何。部分麻烦在于语言的语法取决于用户如何实例化格子:格子的元素成为语法中的终端。我不知道如何在Redex中表达语法上的抽象语法。
与此同时,我试图将lambdaLVar.rkt尽可能地模块化。该文件中定义的语言专用于特定晶格:自然数,max
作为最小上限(lub)运算。 (或者,等价地,由<=
排序的自然数。这是一个非常无聊的格子。)特定于该格子的代码的唯一部分是顶部附近的行(define lub-op max)
,{{1出现在语法中。 (有一个natural
元函数是根据用户指定的lub
函数定义的。后者只是一个Racket函数,因此lub-op
必须转出到Racket来调用{{ 1}}。)
除非能够以对格子选择抽象的方式实际指定lambdaLVar,看起来我应该能够编写一个lambdaLVar的版本,其中最简单的格子 - 只有Bot和Top元素,其中Bot&lt; = Top - 然后使用lub
添加更多内容。例如,我可以定义一种名为lambdaLVar-nats的语言,它专门用于我描述的自然格:
lub-op
然后,为了替换我对lambdaLVar的两个约简关系define-extended-language
和;; Grammar for elements of a lattice of natural numbers.
(define-extended-language lambdaLVar-nats
lambdaLVar
(StoreVal .... ;; Extend the original language
natural))
;; All we have to specify is the lub operation; leq is implicitly <=
(define-metafunction/extension lub lambdaLVar-nats
lub-nats : d d -> d
[(lub-nats d_1 d_2) ,(max (term d_1) (term d_2))])
,我可以定义几个包装器:
slow-rr
我对fast-rr
文档的理解是它应该重新解释(define nats-slow-rr
(extend-reduction-relation slow-rr
lambdaLVar-nats))
(define nats-fast-rr
(extend-reduction-relation fast-rr
lambdaLVar-nats))
和extend-reduction-relation
中的规则,但是使用lambdaLVar-nats。把所有这些放在一起,我尝试运行我所拥有的测试套件,其中一个是新的扩展缩减关系:
slow-rr
我得到的第一件事是合同违规投诉:fast-rr
。小步长的契约行只是> (program-test-suite nats-slow-rr)
,其中small-step-base: input (((l 3)) new) at position 1 does not match its contract
是一个语法非终结符,如果在lambdaLVar-nats下重新解释,则具有新含义,而不是在lambdaLVar下重新解释,因为特定的格子东西。作为一项实验,我在#:contract (small-step-base Config Config)
和Config
上删除了合同。
然后我能够实际运行我的19个测试程序,但其中10个失败了。也许不出所料,所有失败的程序都是以某种方式使用自然数值LVars的程序。 (其余的是“纯粹的”程序,根本不与LVars的存储交互。)因此,失败的测试正是那些使用扩展语法的测试。
所以我一直跟着兔子洞,似乎Redex希望我将所有现有的判断形式和元函数扩展为与lambdaLVar-nats而不是lambdaLVar相关联。这是有道理的,据我所知,它似乎对于判断形式是可行的,但是对于元函数我遇到了麻烦:我希望新的元函数重载同名的旧元函数(因为现有的判断形式正在使用它)似乎没有办法做到这一点。如果我必须重命名元函数,它就会失败,因为无论如何我都要编写全新的判断形式。我想我想要的是一种元函数调用的后期绑定!
我的问题简而言之: Redex中是否有任何方法可以按照我想要的方式参数化语言的定义,或以某种方式扩展语言的定义我想要?我最终只需要编写生成Redex的宏吗?
感谢阅读!
答案 0 :(得分:4)
我问了Racket用户邮件列表;线程开始here。总结最终的讨论:在今天的Redex中,答案是没有,没有办法以我想要的方式参数化语言定义。但是,应该在未来版本的Redex中可以使用模块系统,该模块系统现在正在使用中。
尝试使用Redex现有的扩展表单(define-extended-language
,extend-reduction-relation
等)并不会像我在这里尝试的那样使用它,因为 - 正如我发现的那样 - - 原始元函数不会被传递重新解释为使用扩展语言。但是模块系统显然也会对此有所帮助,因为它可以让你将元函数,判断形式和简化关系打包在一起并同时扩展它们(参见讨论here)。
所以,目前,答案确实是编写一个生成Redex的宏。这样的事情有效:
(define-syntax-rule (define-lambdaLVar-language name lub-op lattice-values ...)
(begin
;; Entire original Redex model goes here, with `natural` replaced with
;; `lattice-values ...`, and instances of `...` replaced with `(... ...)`
))
然后你可以用例如:
来实例化特定的格子(define-lambdaLVar-language lambdaLVar-nat max natural)
我希望Redex尽快获得模块,但与此同时,这似乎运作良好。