问题标签 [undecidable-instances]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
haskell - 为什么这段代码使用 UndecidableInstances 编译,然后生成运行时无限循环?
在使用UndecidableInstances
之前编写一些代码时,我遇到了一些我觉得很奇怪的东西。我无意中创建了一些我认为不应该进行类型检查的代码:
具体来说,convertFoo
当给定任何输入以产生任何输出时,函数会进行类型检查,如evil
函数所示。起初,我以为我可能不小心实现了unsafeCoerce
,但这并不完全正确:实际上尝试调用我的convertFoo
函数(例如,通过执行类似的操作evil 3
)只是进入了无限循环。
我有点模糊地理解发生了什么。我对这个问题的理解是这样的:
ConvertFoo
我定义的实例适用于任何输入和输出,a
并且b
仅受转换函数必须存在的两个附加约束的限制a -> Foo
和Foo -> b
。- 不知何故,该定义能够匹配任何输入和输出类型,因此似乎调用 to
convertFoo :: a -> Foo
正在选择convertFoo
自身的定义,因为无论如何它是唯一可用的定义。 - 由于
convertFoo
无限调用自身,函数进入一个永不终止的无限循环。 - 由于
convertFoo
永不终止,该定义的类型是底部,所以从技术上讲,没有任何类型被违反,并且程序类型检查。
现在,即使上面的理解是正确的,我仍然对为什么整个程序进行类型检查感到困惑。具体来说,鉴于不存在此类实例,我预计ConvertFoo a Foo
and约束会失败。ConvertFoo Foo b
我确实(至少模糊地)理解在选择实例时约束并不重要 - 仅根据实例头选择实例,然后检查约束 - 所以我可以看到这些约束可能会因为我的ConvertFoo a b
实例而很好地解决,这是尽可能宽容的。但是,这将需要解决相同的约束集,我认为这会将类型检查器置于无限循环中,导致 GHC 要么挂起编译,要么给我一个堆栈溢出错误(后者我见过前)。
不过,很明显,类型检查器不会循环,因为它会愉快地触底并愉快地编译我的代码。为什么?在这个特定示例中,实例上下文如何得到满足?为什么这不会给我一个类型错误或产生一个类型检查循环?
haskell - 我可以自动为转换函数生成类型类实例而不会过于宽容吗?
最近,我问了一个关于我创建的生成运行时无限循环的实例的问题,我得到了一个很好的答案!既然我明白了发生了什么,我有一个新问题:我可以修正我的尝试来实现我最初的目标吗?
让我重申并具体澄清我的问题是什么:我想创建一个类型类,用于在我的代码中的一些等效数据类型之间进行转换。我创建的类型类既非常简单又非常通用:它包含一个在任意数据类型之间进行转换的转换函数:
但是,此类型类有一个特定目的:在具有规范表示的特定值类之间进行转换。因此,有一个特定的数据类型是“规范的”,我想使用这个数据类型的属性来减轻我的类型类实现者的负担。
具体来说,考虑两种不同的表示,RepA
和RepB
。我可能会合理地定义一些实例来将这些表示转换为Canonical
:
现在,这立即有用,因为我现在可以同时使用convertRep
这两种表示形式,但它主要只是作为重载convertRep
名称的一种方式。我想做一些更强大的事情:毕竟,我现在已经有效地定义了以下类型的四个函数:
在我看来,根据这些定义,我还应该能够生成以下类型的两个函数:
基本上,由于这两种数据类型都可以转换为/从规范表示,我想直接自动生成相互之间的转换函数。正如我在上述问题中提到的那样,我的尝试看起来像这样:
不幸的是,这个实例过于宽松,当提供两种我认为应该无效的类型时,它会导致生成的代码递归——我还没有定义规范转换的类型。
为了尝试解决这个问题,我考虑了另一种更简单的方法。我想我可以使用两个类型类而不是一个来防止这个递归问题:
现在可以定义一个新函数来执行convertRep
我最初感兴趣的转换:
然而,这是以灵活性为代价的:不再可能在两个非规范表示之间创建直接转换实例。
例如,也许我知道这一点RepA
并且RepB
会非常频繁地互换使用,因此它们会在彼此之间进行相当多的转换。因此,转换为/从的额外步骤Canonical
是浪费时间。我想选择定义一个直接转换实例:
它提供了两种常见类型之间的“快速路径”转换。
总结一下:有没有办法使用 Haskell 的类型系统来完成所有这些目标?
- 给定在表示和规范形式之间转换的函数,在表示之间“生成”转换。
- 可选择在通常转换的实例之间提供“快速路径”。
- 拒绝没有明确定义的实例;也就是说,不允许
ConvertRep Canonical Canonical
(和类似的)创建无限重复并产生底部的实例。
Haskell 类型系统令人印象深刻,但我担心在这种情况下,它的实例解析规则不足以同时完成所有这些目标。
haskell - 无法确定的实例如何真正挂起编译器?
当我第一次阅读有关-XUndecidableInstances
.
事实上,我遇到过很多需要不可判定实例的应用程序,但没有一个应用程序实际上会导致与不可判定性相关的任何问题。卢克的例子是有问题的,原因完全不同
– 好吧,这显然会与任何适当的实例重叠,所以不确定性Group
是我们最不担心的:这实际上是不确定的!
但很公平,因为我一直在脑海中保留“不可判定的实例可能会使编译器挂起”。
当我在 CodeGolf.SE 上阅读这个挑战时,它是从哪里获得的,要求提供可以无限挂起编译器的代码。好吧,这听起来像是在不确定的情况下工作,对吧?
事实证明我无法让他们这样做。以下内容立即编译,至少从 GHC-7.10 开始:
我什至可以使用类方法,它们只会在运行时导致循环:
但是运行时循环并不罕见,您可以在 Haskell98 中轻松编写这些代码。
我还尝试了不同的、不那么直接的循环,例如
同样,在编译时没有问题。
那么,在解析不可判定的类型类实例时,实际上需要什么来挂起编译器呢?
regular-language - 常规语言的图灵机
Sipser 的 TOC 书中的定理 5.3 是关于 Regular_TM = {M | M 是图灵机 (TM),L(M) 是常规语言}。为了达到矛盾,假设 TM R 是 Regular_TM 的决定者,然后 R 用于决定 Acceptance 问题,如打击 TM S 所示:
S = "On input (M,w) where M is a TM and w is a string:
1. Construct the code of TM M2 as follows:
M2 = "On input x:
(a) If x of the form 0^n1^n, accept.
(b) else, run M on w and if M accepts w, then accept."
2. Run R on (M2).
3. If R accepts, accept; if R rejects, reject."
我有两个问题。第一个是 M_2 中的 x 固定吗?如果不是,它来自哪里?
第二个问题。为什么我们关心 M2 中的 x。如果 R 真的是一个决策者,我们为什么要关心检查 x 是否在 0^n1^n 中。那么下面的 TM S' 有效吗?
S = "On input (M,w) where M is a TM and w is a string:
1. Construct the code of TM M2 as follows:
M2 = "On input x: //ignore x
(a) run M on w and if M accepts w, then accept else reject."
2. Run R on (M2).
3. If R accepts, accept; if R rejects, reject."
haskell - 在 Cofree 上编写通用 Monoid;无法确定?
我正在尝试为 Cofree 编写以下 Monoid 实例:
但我收到以下错误:
我以前遇到过 Undecidable Instances ,但我不确定为什么这是不可判定的,我该如何解决?我需要添加 UndecidableInstances 吗?谢谢!!
turing-machines - 图灵机可判定性模糊案例
1) 接受语言 L = {ε} 的图灵机 M 是否不接受任何条目?
一方面,我认为它可能是错误的,因为空词可能是一个条目,但另一方面,我认为这可能是一个无法确定的问题。
2)是否每台可判定语言的图灵机在任何输入时都会停止?
同样的想法,直觉上我会说是的,由于可判定的定义,但我不知道,有什么困扰我。
3)回文的语言是否可以确定,无论 aphabet 是什么?
对于这一点,我几乎毫不怀疑它是错误的,因为有了赖斯定理,我们可以证明,这个问题是不可判定的。
haskell - 由于 Paterson 的条件,Haskell 类型类约束无法解决
我正在尝试使用索引嵌套注释构建 AST。我添加了一个用于在顶层剥离注释的类型类,并尝试提供默认实例,有效地说明“如果您知道如何自行剥离注释,那么您就知道如何在特定 AST 节点处剥离注释。”
由于我的一个树节点是一个Nat
索引谓词,并且它的父节点存在地量化了这个变量,所以当我尝试为父节点编写实例时,我陷入了帕特森的条件。也就是说,我在断言中的类型变量比在头脑中的要多。
如果我打开UndecidableInstances
,则 GHC 无法将变量与 kind 统一起来Nat
。
如果我进一步打开AllowAmbiguousTypes
,那么我会得到一个更荒谬的错误,它说它找不到实例,尽管它正在寻找的实例在类型实例的断言中。
我的问题是:
- 这实际上是一个不好的实例,还是类型检查器过于保守?
- 如果它不好或无法解决问题,我还能如何提供这种默认的剥离行为?
这是最小的代码(我去掉了对类型错误不重要的位,所以有些位可能看起来是多余的):
这是没有的确切错误UndecidableInstances
:
这是它的一个:
这是一个AllowAmbiguousTypes
:
编辑:
正如 Daniel Wagner 建议的那样,一种解决方案是在实例中进行PeelableAnn PredicateAnn ann
断言。PeelableAST Literal ann
但是,我从来没有peelA
在定义中使用由 PeelableAnnPeelableAST Literal ann
定义的,我希望这个实例作为默认行为并且能够通过直接提供一个PeelableAST (Predicate n) ann
实例来覆盖它。换句话说,剥离可能本质上是上下文相关的。
既然PeelableAnn PredicateAnn ann
是要求PeelableAST (Predicate n) ann
,我觉得GHC应该能找到并满足这个条件。
我可以简单地拥有一个虚假PeelableAnn PredicateAnn ann
实例,而只会被更具体的实例忽略,但这很hacky
haskell - GHC 由于 UndecidableSuperClasses 卡住 - 预期的行为或错误?
以下代码段使 GHC(使用 8.6.2 和 8.4.4 检查)在编译期间卡住:
我认为它被卡住了,因为t
GHC 试图找到C T
,这导致F T C
通过类型族扩展F
回C T
,这就是它正在寻找的(无限循环)。
我想理论上 GHC 可以说它C T
从自身达到了它的要求,并且任何依赖于自身的东西都可以递归地工作,还是我误解了什么?
旁注:在我偶然发现这种行为的真实示例中,我能够实现我想要的,而编译器不会被替换为UndecidableSuperClasses
卡住Data.Constraint.Dict
。
haskell - 在没有 UndecidableInstances 的实例头中使用 Barbies 的 AllBF
我想在实例头中使用AllBF
from ,如下所示:barbies
由于隐藏的种类多态性,这失败了。西蒙 说:
• 变量
k
在约束中出现的频率AllBF MyClass f b
高于在实例头部中出现的频率MyClass (Barbie b f)
(UndecidableInstances
用于允许这样做)
我想避开UndecidableInstances
这里。我尝试过的一件事是使我的实例单态为f
:
但是,这会导致另一个错误:
• 非法嵌套约束
AllBF MyClass f b
(UndecidableInstances
用于允许这样做)
天真地,我尝试内联 的定义AllBF
,但这并没有改变任何东西:
• 非法嵌套约束
AllB (ClassF MyClass f) b
(UndecidableInstances
用于允许这样做)
有没有办法在不打开的情况下创建这个实例UndecidableInstances
?
haskell - 类型级别集的传递“子集”类
我正在使用 Dominic Orchard 的type-level-sets库,该库非常接近他的论文。
我正在构建一个 DSL,用于在同步并发程序期间表达各方之间的通信。我需要的一件事是能够表达涉及原始社区子集的“子程序”;这将与fromUniversal
.
这是我的代码的简化版本:
在_clique
中,有提供Subset recipients clq
和的上下文Subset csl parties
;我需要 GHC 以某种方式理解这意味着Subset recipients parties
. 但是没有这样的实例可用。
为了类型级别集的目的,我如何表示“子集”的传递性?
这是错误消息:
我试着简单地添加
to Lib.hs (apparently Subset
isn't closed-world; I think); this gives a variety of different error messages depending what compiler options I use, or if I swap out OVERLAPS
for INCOHERENT
. The jist of it seems to be that GHC can't pick an instance to use, even if I promise it'll be ok.
I tried making the recipient
type explicit in _clique
(so I can just add the needed Subset recipients parties
to the context), but it seems like no matter what I do reinterpret
always introduces/requires a "fresh" x
and/or recipients
; I haven't found a way of providing the context for the type-variable that's actually used.
It seems unlikely that this is impossible, but I've been stuck on it for a day and I'm out of my depth.
Edit
我一直在使用以下解决方案进行该项目;这显然是平庸的。具体来说,除了传递性之外,还有很多属性很好,比如两个集合都是第三个集合的子集,那么它们的并集也是第三个集合的子集。对于 Haskell 的类型系统来说,“免费”获得这样的属性可能太过分了……