18

Applicative实例Data.Sequence通常表现得非常好。几乎所有的方法在时间和空间上都是渐进渐近最优的。也就是说,给定完全强制/实现的输入,可以在渐近最优时间和内存驻留中访问结果的任何部分。还有一个例外:(<*). 我只知道两种实现它的方法:

  1. 默认实现

    xs <* ys = liftA2 const xs ys
    

    这种实现需要O(|xs| * |ys|)时间和空间来完全实现结果,但只能O(log(min(k, |xs|*|ys|-k)))访问k结果的第 th 元素。

  2. “一元”实现

    xs <* ys = xs >>= replicate (length ys)
    

    这只需要O(|xs| * log |ys|)时间和空间,但不是增量的;访问结果的任意元素需要O(|xs| * log |ys|)时间和空间。

长期以来,我一直认为应该可以拥有我们的蛋糕并吃掉它,但我从来没有能够很好地在脑海中处理这些碎片以到达那里。这样做似乎需要结合 和 的实现中的想法(但不是实际代码liftA2replicate。如何才能做到这一点?


注意:肯定没有必要加入rigidify类似liftA2. 类似replicate的部分肯定只产生我们rigidify用来从用户提供的树中获取的那种“刚性”结构。

更新(2020 年 4 月 6 日)

任务完成!我设法找到了办法。不幸的是,这对我来说有点太复杂了,无法理解正在发生的一切,而且代码......相当不透明。我会赞成并接受对我所写内容的一个很好的解释,并且也会很高兴地接受关于提高清晰度的建议和在 GitHub 上的评论。

更新 2

非常感谢 Li-Yao Xia 和 Bertram Felgenhauer 帮助清理和记录我的代码草案。现在它的理解难度大大降低,并将出现在containers. 得到一个答案来结束这个问题仍然会很好。

4

0 回答 0