optimization - 在 Haskell 中, concat 懒惰地构建一个列表,但我自己的版本有一个扭曲,没有

标签 optimization haskell

我正在尝试制作一个相对简单的函数,它几乎是 concat 但有点扭曲。它应该将每个列表的最后一个和第一个元素二进制或组合在一起,并在此过程中将它们组合起来。我正在努力学习编写可以利用 Data.List.Stream 中的流融合功能的代码

我检查了 base 中的 concat 是否完成了所需的操作并懒惰地构建了列表,但是,我创建的这个版本没有。在基础中, concat 指定如下:

concat :: [[a]] -> [a]
concat = foldr (++) []

(++) :: [a] -> [a] -> [a]
(++) []     ys = ys
(++) (x:xs) ys = x : xs ++ ys

这是我的代码:
bconcat :: [[Word8]] -> [Word8]
bconcat = foldr1 bappend

bappend :: [Word8] -> [Word8] -> [Word8]
bappend as bs = init as ++ (last as .|. head bs) : tail bs

我的问题是,我该如何编写这个列表以便懒惰地构建列表?我什至尝试通过模仿 base 中的 (++) 定义来编写 bappend,但这并没有什么不同。

目前,我使用以下代码,它按我想要的方式工作,但性能落后于 concat。此外,它使用了我想避免的显式递归。
bconcat :: [[Word8]] -> [Word8]
bconcat (a:b:xs) = init a ++ bconcat ((bappend (last a) b):xs)
bconcat (a:[]) = a
bconcat [] = []

bappend :: Word8 -> [Word8] -> [Word8]
bappend !a bs = (a .|. head bs) : tail bs

所以,我的问题是,我该如何编写这段代码,以便它懒惰地构建列表并且没有显式递归?

感谢您的时间。

编辑:

目前,我的主要兴趣是使用标准组合器制作干净、简洁和不稳定的代码。我仍然是功能性思维的初学者,并且希望看到一种合理有效的方式将它们在这里使用。

最佳答案

你的定义对我来说看起来很严格。例如,尝试评估

length $ bconcat [[1,2,3],[4,undefined,6]]

但是您可能正在为 .| 建立 thunk。表达。也许你想强制它。

如果它们不能很好地自动融合,您总是可以自己融合事物:
 bconcat [] = error "bconcat: empty outer list"
 bconcat (xs:xss) = loop xss xs
   where loop [] ys = ys
         loop ((x:xs):xss) [y] = let z = x .|. y in seq z $ z : loop xss xs
         loop ([]:_) _ = error "bconcat: empty inner list"
         loop xss (y:ys) = y : loop xss ys

关于optimization - 在 Haskell 中, concat 懒惰地构建一个列表,但我自己的版本有一个扭曲,没有,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5362292/

相关文章:

c++11 - 因式分解 Eigen3 临时值以提高计算速度

python - 优化使用python 3生成大量随机数

R - 速度优化和国际象棋排名

haskell - 在 Haskell 中查找函数的行号

haskell - GHCI 不能在编译时推断 Eq 类,但在运行时可以吗?

haskell - 记住满足约束的结果

python - 拼接 Pandas Dataframe 的优化方法

python - 如何指定只允许某些第一个组合的 itertools 排列?

haskell - Haskell 特里树中的太空泄漏

regex - Haskell:我应该费心编译正则表达式吗?