我正在开发基于使用some existing code库的unbound的项目。
代码使用unsafeUnbind
一堆,这导致我的问题。
我已尝试使用freshen
,但收到以下错误:
error "fresh encountered bound name!
Please report this as a bug."
我想知道:
FreshM
monad中使用?或者他们的方法是在没有Fresh
的情况下执行lambda应用程序?freshen
提供哪些值,以避免列出的错误?unsafeUnbind
,在什么条件下可以安全使用?答案 0 :(得分:6)
该库是否完全在
Fresh
M monad中使用?或者他们的方法是在没有Fresh
的情况下执行lambda应用程序?
在大多数情况下,您需要在Fresh
或LFresh
monad中操作。
我可以为
freshen
提供哪些值,以避免列出的错误?
所以我认为您收到错误的原因是因为您将术语传递给freshen
而不是模式。在Unbound中,模式类似于名称的概括:单个Name E
是由单个变量组成的模式,代表E
s,但(p1, p2)
或[p]
是模式分别由一对模式p1
和p2
或模式列表p
组成。例如,这允许您定义同时绑定两个变量的术语。其他更奇特的类型构造函数包括Embed t
和Rebind p1 p2
前者创建一个模式,在模式中嵌入一个术语,而后者类似于(p1,p2)
,但p1
中的名称除外}范围超过p2
(例如,如果p2
中包含Embed
个ed术语,p1
将超出这些术语的范围。这非常强大,因为它可以让您像依赖类型语言一样定义Scheme的let*
形式或望远镜等内容。 (详见论文)。
现在最终类型构造函数Bind p t
将术语和类型组合在一起:术语Bind p t
表示p
中的名称绑定在Bind p t
和范围内超过t
。因此,data Expr = Lam (Bind Var Expr) | App Expr Expr | V Var
type Var = Name Expr
可以构造一个(无类型的)lambda术语。
回到freshen
。您只应在模式上调用freshen
,因此在Bind p t
类型的内容上调用它是不正确的(我怀疑您看到的错误消息的来源) - 您应该仅在p
上调用它,然后将结果排列应用于术语t
,以应用freshen
构造的重命名。
如果我最终使用`unsafeUnbind,在什么条件下使用它是安全的?
我使用它的地方是,如果我需要暂时潜入一个活页夹,并做一些我知道肯定对名称没有任何操作的操作。一个例子可能是从一个术语中收集一些源位置注释,或者用一个封闭的术语替换一些全局常量。此外,如果您可以保证已经重命名了您正在使用的术语,那么您unsafeUnbind
的任何名称都将是唯一的。
希望这有帮助。
PS:我维护unbound-generics这是Unbound的克隆,但是使用GHC.Generics而不是RepLib。