List 为什么可以';关于一些无限列表的原因?

List 为什么可以';关于一些无限列表的原因?,list,haskell,ghc,compiler-optimization,List,Haskell,Ghc,Compiler Optimization,让我想到了Haskell处理无限列表的能力。在StackOverflow上有关于无限列表的问题和答案,我理解为什么我们不能对所有无限列表都有一个通解,但为什么Haskell不能对一些无限列表进行推理呢 让我们使用第一个链接问题中的示例: list1 = [1..] list2 = [x | x <- list1, x <= 4] print list2 $ [1,2,3,4 对于Int和Integer类型,枚举函数具有以下含义: 序列enumFrome1是列表[e1,e1+1,e

让我想到了Haskell处理无限列表的能力。在StackOverflow上有关于无限列表的问题和答案,我理解为什么我们不能对所有无限列表都有一个通解,但为什么Haskell不能对一些无限列表进行推理呢

让我们使用第一个链接问题中的示例:

list1 = [1..]
list2 = [x | x <- list1, x <= 4]
print list2
$ [1,2,3,4
对于Int和Integer类型,枚举函数具有以下含义:

  • 序列enumFrom
    e1
    是列表[
    e1
    e1
    +1,
    e1
    +2,…]
在回答另一个问题时,@chepner写道:

您知道列表是单调递增的,但Haskell不知道

在我看来,这些用户所做的声明似乎不符合标准。Haskell使用单调递增以有序方式创建列表。Haskell应该知道列表是有序的和单调的。那么,为什么它不能对这个无限列表进行推理,使其变成
[x | x

那么,为什么不能对这个无限列表进行推理,从理论上讲,我们可以想象一个重写规则,比如

{-# RULES
  "filterEnumFrom" forall (n :: Int) (m :: Int).
                     filter (< n) (enumFrom m) = [m..(n-1)]
  #-}

这可能会更容易优化。

Good q。我只是想把它链接到这里。Haskell不会推断任何东西,除非语言程序的开发人员允许它进行推断。没有免费的午餐。显然,您可以设计语言,使某些列表自动标记为正在增加,但这会增加已经相当复杂的语言的复杂性。@JohnColeman这是公平的,在管理无限列表方面对我来说似乎是一个合乎逻辑的跳跃。我认为Haskell的设计师/开发人员在语言设计/抽象数学方面要熟练得多,并且有一个很好的理论理由解释为什么没有做到这一点,而不是n实用的。列表理解对所有类型的列表都是统一的,不考虑任何进一步的结构(即
[1..]
具有type
Enum t,Num t=>[t]
,而不仅仅是
[t]
)。其次,谓词
x Bool
,因此随着列表元素的增加,其行为的相关信息不可用。正如其他人所提到的,一旦创建了列表,有关其创建方式的信息就会丢失。您需要以某种方式保留它;典型的方法是创建自己的类型来保留排序信息。请类型符合
List
typeclass,您可以在普通
Ord a=>List a
适合的任何地方使用它。
[ e | True ]         = [ e ]
[ e | q ]            = [ e | q, True ]
[ e | b, Q ]         = if b then [ e | Q ] else []
[ e | p <- l, Q ]    = let ok p = [ e | Q ]
                           ok _ = []
                       in concatMap ok l
[ e | let decls, Q ] = let decls in [ e | Q ]
[x | x <- [1..], x <= 4]

-- apply rule 4 --
let ok x = [ x | x <= 4 ]
    ok _ = []
in concatMap ok [1..]

-- eliminate unreachable clause in ok --
let ok x = [ x | x <= 4 ]
in concatMap ok [1..]

-- apply rule 2 --
let ok x = [ x | x <= 4, True ]
in concatMap ok [1..]

-- apply rule 3 --
let ok x = if x <= 4 then [ x | True ] else []
in concatMap ok [1..]

-- apply rule 1 --
let ok x = if x <= 4 then [ x ] else []
in concatMap ok [1..]

-- inline ok --
concatMap (\x -> if x <= 4 then [ x ] else []) [1..]
{-# RULES
  "filterEnumFrom" forall (n :: Int) (m :: Int).
                     filter (< n) (enumFrom m) = [m..(n-1)]
  #-}
data List a where
  EnumFromTo :: Enum a => a -> Maybe a -> List a
  Filter :: (a -> Bool) -> List a -> List a 
  Unstructured :: [a] -> List a