通常,foldl
避免使用foldl'
or foldr
。引用真实世界的 Haskell:
由于 foldl 的重击行为,明智的做法是在实际程序中避免使用此功能:即使它没有彻底失败,它也会不必要地低效。相反,导入 Data.List 并使用 foldl'。
然而,一些 Prelude 函数是根据它定义的(例如(\\)
和unionBy
)。为什么是这样?是不是不要对这些功能引入太多的严格性?
通常,foldl
避免使用foldl'
or foldr
。引用真实世界的 Haskell:
由于 foldl 的重击行为,明智的做法是在实际程序中避免使用此功能:即使它没有彻底失败,它也会不必要地低效。相反,导入 Data.List 并使用 foldl'。
然而,一些 Prelude 函数是根据它定义的(例如(\\)
和unionBy
)。为什么是这样?是不是不要对这些功能引入太多的严格性?
Prelude 是在foldl'
存在之前设计的,从那时起就一直存在保持向后兼容性的压力(关于严格性,正如您所提到的)。
在 和 的情况下(\\)
,unionBy
折叠函数具有类型
foo :: [a] -> b -> [a]
并foo xs y
从 中删除最多一个元素xs
,因此 usingfoldl'
通常不会在那里购买任何东西,thunk 将构建在最顶部的右侧(:)
而不是其上方。
据我所知,这不会在严格性方面产生影响,只有在需要将结果评估为弱头正常形式时才会评估两个折叠,并且只要foldl'
会产生 a _|_
,也会产生foldl
。
在这两种情况下,累加器都是类型[a]
。我看不出将列表强制为弱头范式会产生巨大的影响,并且引入这种部分严格性似乎有些武断。