如何正确使用 seq In list comprehension?
How to properly use seq In list comprehension?
我试图在列表推导中使用 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
不工作?
你没有给 lst
一个具体的类型所以对于 ghci 它是一个新的 instance/value 每次你使用它(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 指出的那样,关于 parameters/invisible-functions 的评论可能具有误导性甚至是错误的。
遗憾的是,我不能声称真的知道 GHCi 如何处理这个问题(当我找到来源时我会很乐意添加一些东西)但到目前为止我的直觉是,GHCi does/cannot 创造了一个价值直到所有dictionaries 类型-class 约束是已知的 - 所以如果没有约束它可以并且将创建值(在运行时没有类型所以这没问题) .
在上面的示例中,隐式 Num
约束(0
、1
、9
和 +
)要求这样一个 相关类型的 Num
实例的字典。
我试图在列表推导中使用 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
不工作?
你没有给 lst
一个具体的类型所以对于 ghci 它是一个新的 instance/value 每次你使用它(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 指出的那样,关于 parameters/invisible-functions 的评论可能具有误导性甚至是错误的。
遗憾的是,我不能声称真的知道 GHCi 如何处理这个问题(当我找到来源时我会很乐意添加一些东西)但到目前为止我的直觉是,GHCi does/cannot 创造了一个价值直到所有dictionaries 类型-class 约束是已知的 - 所以如果没有约束它可以并且将创建值(在运行时没有类型所以这没问题) .
在上面的示例中,隐式 Num
约束(0
、1
、9
和 +
)要求这样一个 相关类型的 Num
实例的字典。