You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell数据类型惰性引发<<loop>>错误的原因咨询

为什么这段Haskell代码会触发<>错误?

你的代码如下:

weird = ([1],[2]) <> weird
main = print (head $ fst weird)

你的直观理解存在偏差,核心问题出在元组的Semigroup实例实现和递归绑定的求值逻辑上:

  • 元组的<>运算规则:对于(a,b) <> (c,d),Haskell会先对右侧的元组(c,d)进行模式匹配,提取出两个元素后,再分别对左右元组的对应元素执行<>运算,最终得到(a<>c, b<>d)。
  • 你的代码中weird = ([1],[2]) <> weird,等价于要求Haskell计算:weird = let (c,d) = weird in ([1]<>c, [2]<>d)。这时候求值器陷入了循环:
    1. 要执行<>运算,必须先把weird匹配成(c,d),也就是需要weird的顶层构造器是元组(,);
    2. 但weird本身的定义就是<>运算的结果,而<>运算的结果又是一个元组,这意味着必须先完成<>运算才能得到weird的构造器;
    3. 两者互相依赖,导致求值器无法推进,最终触发<<loop>>错误。

你以为的fst weird = [1] ++ fst weird之所以不成立,是因为这个推导的前提是fst (([1],[2]) <> weird) = [1] <> fst weird,但这个等式成立的前提是weird已经是一个能被匹配成元组的有效值——而你的递归定义里,weird根本无法完成这个匹配步骤,自然到不了列表拼接的阶段。

对比能正常运行的写法:

weird = (weirdFst, weirdSnd)
  where
    weirdFst = [1] ++ weirdFst
    weirdSnd = [2] ++ weirdSnd

main = print (head $ fst weird)

这里weird直接由两个递归列表构造为元组,不需要依赖<>运算的模式匹配。当取fst weird时,直接得到weirdFst,而weirdFst = 1 : weirdFst,head可以直接取到第一个元素1,不需要求值整个递归列表。

内容的提问来源于stack exchange,提问作者141592653

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 07:23:20