gpt4 book ai didi

haskell - GHCi 中的严格列表评估

转载 作者:行者123 更新时间:2023-12-04 15:31:28 29 4
gpt4 key购买 nike

考虑程序:

l = [0..10]
l' = map (+1) [0..10]

使用 GHCi 运行它,并键入 :sprint l:sprint l' 将显示两个列表都未计算。但是,在运行 length llength l' 然后再次使用 sprint 之后:

l = [0,1,2,3,4,5,6,7,8,9,10]

l' = [_,_,_,_,_,_,_,_,_,_,_]

我做了类似的实验,并尝试使用 let 将变量绑定(bind)到 GHCi 中的列表,但是仅在 l 的情况下(在程序 top- 中定义如上) level) 是总是完全评估的列表。

这些行为都指向优化功能,但我想知道是否有更详尽的“幕后”答案(策略)。

最佳答案

原始 [0..10] 列表的元素在两种情况下都进行了评估。 l' 案例中未计算的是将 (+1) 应用于列表元素的结果。相反,如果我们 map the function strictly 会发生什么:

GHCi> import Control.Monad
GHCi> l'' = (+1) <$!> [0 :: Integer ..10]
GHCi> :sprint l''
l'' = _
GHCi> length l''
11
GHCi> :sprint l''
l'' = [1,2,3,4,5,6,7,8,9,10,11]

(请注意,我对整数文字进行了专门处理,因此 GHCi 提示中没有单态限制不会导致与从文件加载代码时得到的结果不同。)

值得注意的是 enumFromTo 对于 Integer(使用范围归结为),as implemented by base , 评估元素以了解何时停止生成它们。也就是说,不是 length 强制列表元素,正如我们希望通过查看 its definition 得到的那样。 :

length                  :: [a] -> Int
length xs = lenAcc xs 0

lenAcc :: [a] -> Int -> Int
lenAcc [] n = n
lenAcc (_:ys) n = lenAcc ys (n+1)

为了更好地了解 length 在这里的行为,我们可能会尝试使用 replicate 生成的列表重复您的实验。 (与 length 一样,不查看元素)在未完全评估的值上:

GHCi> n = 2 * (7 :: Integer)  -- let-bindings are lazy.
GHCi> :sprint n
n = _
GHCi> l''' = replicate 3 n
GHCi> :sprint l'''
l''' = _
GHCi> length l'''
3
GHCi> :sprint l'''
l''' = [_,_,_]

关于haskell - GHCi 中的严格列表评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61189185/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com