我试图在列表理解中使用seq来强制对生成的元素进行计算,但是:sprint告诉我,我的列表实际上是没有计算的。例如:
Prelude> let foo a b = a + b
Prelude> let bar c = c + 1
Prelude> let lst = [bar $ foo x y | y <- [0..9], x <- [0..9]]
Prelude> :sprint lst
lst = _
Prelude> seq lst ()
()
Prelude> :sprint lst
lst = _但其他人的map似乎运行正常:
Prelude> let xs = map (+1) [1..10] :: [Int]
Prelude> :sprint xs
xs = _
Prelude> seq xs ()
()
Prelude> :sprint xs
xs = _ : _为什么我的seq不能工作?
发布于 2021-04-29 17:36:52
您没有给lst一个具体的类型,所以每次使用它时,ghci都是一个新的实例/值( GHCi将为它选择一个默认类型)
如果您没有更改任何内容,您甚至应该看到这样的警告:
<interactive>:19:1: warning: [-Wtype-defaults]
• Defaulting the following constraints to type ‘Integer’
(Show a0) arising from a use of ‘print’ at <interactive>:19:1-10
(Num a0) arising from a use of ‘it’ at <interactive>:19:1-10
(Enum a0) arising from a use of ‘it’ at <interactive>:19:1-10
• In a stmt of an interactive GHCi command: print it添加:: [Int],它应该可以工作:
> let foo a b = a + b
> let bar c = c + 1
> let lst = [bar $ foo x y | y <- [0..9], x <- [0..9]] :: [Int]
> :sprint lst
lst = _
> seq lst ()
()
> :sprint lst
lst = _ : _我喜欢把泛型类型想成有额外的不可见参数:类型参数的类型--所以它更像是一个函数而不是一个值;(当然,实际上它并不完全是这样的,但是它帮助我解决了这样的问题。)
编辑( @dfeuer )指出,关于参数/不可见函数的评论可能是误导的,甚至是错误的。
遗憾的是,我不能说我真的知道GHCi是如何处理这个问题的(当我找到一个源时,我会很高兴地添加一些东西),但到目前为止,我的直觉是,GHCi确实/不能创建一个值,直到所有类型的字典都知道了--类约束--所以如果没有约束,它可以并且将创建值(在运行时,没有类型,所以这是没有问题的)。
在上面的示例中,隐式Num约束(0、1、9和+)要求对所涉及类型的Num实例使用这样的字典。
https://stackoverflow.com/questions/67322367
复制相似问题