为什么我需要在Redex中使用评估上下文?

时间:2017-02-02 19:14:40

标签: racket semantics plt-redex redex

完全可以在不使用评估上下文的情况下为我的语言编写评估规则。我的语义完全是按值进行调用,并且不允许该术语在lambda内部逐步进行。尽管如此,我所看到的所有资源都以某种方式使用了减少上下文。是否有充分的理由使用我缺少的背景?

1 个答案:

答案 0 :(得分:3)

简短回答:你没有,但对他们来说更容易。

答案很长:几乎所有你都会使用评估上下文,你可以在缩减关系中使用不同的缩减规则,它会变得更加令人讨厌,特别是当你对除了最小的语言之外的任何东西进行建模时。 / p>

假设你想用值lambda演算来模拟调用。它的语言(没有评估上下文)将是:

(define-language Lv
  (v (λ (x) e))
  (e v
     (e e))
  (x variable-not-otherwise-mentioned)
  #:binding-forms
  (λ (x) e #:refers-to x))

(此处,最后两行用于利用Redex的capture avoiding substitution

现在,让我们尝试在不使用评估上下文的情况下为这种语言制作语义。有两个地方我们可以扩展子表达式,操作符和函数应用程序的操作数。因此,包括正常β减少的那些给我们:

(define red
  (reduction-relation
   Lv
   (--> (e_1 e_2)
        (v_1 e_2)
        (where v_1 ,(first (apply-reduction-relation red (term e_1)))))
   (--> (v_1 e_2)
        (v_1 v_2)
        (where v_2 ,(first (apply-reduction-relation red (term e_2)))))
   (--> ((λ (x) e) e_2)
        (substitute e x e_2))))

这不是太糟糕,但请记住,我们必须为每个可以评估子表达式的地方添加一个额外的规则。因此,如果需要自己的规则等,那么就需要自己的规则。请记住,这是基于每种形式的规则。

更简单的方法是使用评估上下文,它允许我们指定哪些表达式具有可以采取步骤的子表达式,以及它们应该发生的顺序。所以让我们尝试重写我们的{{1}语言与评估上下文:

Lv

现在它的行数增加了三行,但是这告诉redex我们将在评估上下文(define-language Lv2 (v (λ (x) e)) (e v (e e)) (x variable-not-otherwise-mentioned) (E hole (E e) (v E)) #:binding-forms (λ (x) e #:refers-to x)) 中评估我们的表达式,并且当它完成对表达式的评估时,将它放入上下文中(其中{{1}可以这么说是顶级的上下文。因此,我们可以将减少关系减少到只有一个规则,β减少:

E

在这里,我们使用hole表示我们位于(define red2 (reduction-relation Lv2 (--> (in-hole E ((λ (x) e) e_2)) (in-hole E (substitute e x e_2))))) 之后的一个洞中,如上所示。这遵循值语义调用,因为空洞只能在应用程序中从左到右显示。

你可以想象,如果你有一个包含许多子表达式的更大的计算,这将使你免于编写大量的约简规则。

所以,回顾一下,你不需要,它只会使你的模型更短。