Haskell “的数学意义是什么?”;全部(=1)[1,1..];不终止?

Haskell “的数学意义是什么?”;全部(=1)[1,1..];不终止?,haskell,math,data-structures,computer-science,infinite-recursion,Haskell,Math,Data Structures,Computer Science,Infinite Recursion,直观地说,我希望all(=1)[1,1..]的“数学”答案是True,因为列表中只包含1的所有元素都等于1。然而,我理解“计算上”,计算无限列表以检查每个元素是否等于1的过程永远不会终止,因此表达式将“计算”到底部或⊥ 我觉得这个结果违反直觉,有点令人不安。我认为,这个列表是无限的,这一事实在数学和计算上混淆了这个问题,我希望听到在这方面有一些见解和经验的任何人的意见 我的问题是,哪一个是数学上最正确的答案⊥或为真? 对于为什么一个答案比另一个答案更正确的一些详细说明也将不胜感激 编辑:这可能间

直观地说,我希望
all(=1)[1,1..]
的“数学”答案是
True
,因为列表中只包含1的所有元素都等于1。然而,我理解“计算上”,计算无限列表以检查每个元素是否等于1的过程永远不会终止,因此表达式将“计算”到底部或

我觉得这个结果违反直觉,有点令人不安。我认为,这个列表是无限的,这一事实在数学和计算上混淆了这个问题,我希望听到在这方面有一些见解和经验的任何人的意见

我的问题是,哪一个是数学上最正确的答案<代码>⊥
为真
? 对于为什么一个答案比另一个答案更正确的一些详细说明也将不胜感激


编辑:这可能间接地和(程序是证明,类型是定理)和有关。如果我没记错的话,其中一个不完全性定理可以(令人难以置信地粗略)概括为“足够强大的形式系统(如数学或编程语言)无法证明系统中可以表达的所有真实语句”

我对可计算性知之甚少,无法正确回答这个问题,但我确实从语言设计的简单性中得到了安慰。在这种情况下,我发现
all
不必知道任何关于它所给出的输入的信息,这是简单而优雅的。可以说,对于人类来说,对你给出的片段进行推理更容易

当然,现在对无限列表的理解最好能告诉
all
这是一个无限列表。但是这就是它所说的“具有这种价值”。对重复序列使用更通用的元数据会更成功地达到优化目的,但我认为简单性会降低,复杂性也会增加

all (==1) [1,1..]
是序列的最小上界

all (==1) (⊥)
all (==1) (1 : ⊥)
all (==1) (1 : 1 : ⊥)
...
这个序列的所有项都是⊥, 所以最小上界也是⊥. (所有Haskell函数都是连续的:保留最小上界。)


这是对Haskell的使用,不依赖于(直接)选择任何特定的评估策略。

在编程中,我们使用的不是经典逻辑,而是直觉(构造性)逻辑。我们仍然可以将类型解释为定理,但我们不关心这些定理的真实性;相反,我们讨论它们是否具有建设性的可证明性。尽管
all(=1)[1,1..]
是真的,但我们无法在Haskell中证明它,所以我们得到了⊥ (这里是一个无限循环)


在建构逻辑中,我们既没有排除中间律,也没有双重否定消去律。Haskell函数类型
all(=1)::[Int]->Bool
不代表定理[Int]→ Bool,这将是一个总函数;它表示定理[Int]→ 波尔。如果
all
可以通过产生一个结果来证明定理,那么该结果将是
Bool
类型;否则,结果是底部。

好问题,我喜欢!但它可能属于cstheory或cs.se。在这种情况下,bottom vs.true对于稍微不同的问题都是同样有效的答案。对于他们回答的问题,两者在数学上都是正确的。“数学上正确”是什么意思?当你仔细回答这个问题时,你也会回答你自己的问题。正确的思考方式是列表类型不能正确地表示循环列表,人们可以观察循环。如果您定义了一个允许观察循环的数据类型,那么您将不会发现编写一个在有限时间内检查无限循环列表的
all
太困难。在某些语义不同于Haskell的语言中,这样的数据类型可能很容易定义,例如,由于指针相等-也许这就是导致您的直觉在这里失败的原因。@user2407038识别循环只会让您部分达到目的,并且我似乎不太满意。那么
all(>0)[1..]
呢?这个“应该”是
真的
,但是这个列表是无限的,没有一个周期可以让你更容易地发现它。它有多严格?当用
True
替换
all(=1)[1,1..]
时,优化技术会破坏一些重要的东西吗?@AlexeyBirukov 1)你也可以用
True
替换
let x=True&&x in x
?或者
让x=x在x中
?2) 优化器无法发现所有这些情况,因为问题是无法确定的。让你的代码突然停止工作,因为某些优化不再起作用,这看起来很脆弱。@AlexeyBirukov:正如chi所说,乐观主义者做这种事情是没有意义的。少数情况下,这是可能的,就像给定的例子一样,是微不足道的,因此不会给您带来太多好处。好吧,但是“循环不变代码运动”优化家族呢?它被证明是有用的,至少对于C类语言是有用的。编译器是否可以在内部进行超越指称语义的猜测,比如
map(2*)[1,1..]
-->
[2,2..]
?@AlexeyBirukov,我不知道你所说的“超越指称语义”是什么意思
map(2*)[1,1..]
[2,2..]
具有相同的表示,因此用一个替换另一个没有问题。