Performance 带折叠的优化
我只是好奇是否有(仅一阶多态性)折叠优化 对于地图,存在着毁林现象:Performance 带折叠的优化,performance,functional-programming,ocaml,fold,Performance,Functional Programming,Ocaml,Fold,我只是好奇是否有(仅一阶多态性)折叠优化 对于地图,存在着毁林现象:mapg(mapfls)=>mapg(g.f)ls,以及rev(mapfls)=>rev_-mapfls(在Ocaml中更快) 但是fold是如此强大,似乎无法进行任何优化。显而易见的是: fold_left f acc (List.map g li) => fold_left (fun acc x -> f acc (g x)) acc li fold_right f li acc => fold_left
mapg(mapfls)=>mapg(g.f)ls
,以及rev(mapfls)=>rev_-mapfls
(在Ocaml中更快)
但是fold是如此强大,似乎无法进行任何优化。显而易见的是:
fold_left f acc (List.map g li) => fold_left (fun acc x -> f acc (g x)) acc li
fold_right f li acc => fold_left f acc li (* if (f,acc) is a monoid *)
你可能会对关于“香蕉、镜头、信封和带刺铁丝网的函数式编程”主题的经典论文感兴趣。然而,请注意,它是技术性的,并且具有难以穿透的符号
编辑:我的第一条规则的第一个版本是错误的,多亏了文森特·雨果的编辑。你可以在褶皱上使用森林砍伐。事实上,
map/map
fusion就是一个特例
诀窍是用一个特殊的build
函数替换列表构造:
build :: (forall b. (a -> b -> b) -> b -> b) -> [a]
build g = g (:) []
现在,使用foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr c n [] = n
foldr c n (x:xs) = c x (foldr c n xs)
我们有以下等价物:
foldr c n (build g) == g c n
(事实上,这仅在某些情况下是正确的,但在一般情况下是正确的。有关详细信息,请参阅)
如果使用build
编写列表生成函数(包括map
),使用foldr
编写用户,则上述等式可以删除大多数中间列表。Haskell的列表理解被翻译成build
和foldr
的组合
这种方法的缺点是它不能处理左折叠。不过处理得很好。它将列表生成器和转换器表示为流(共导数据类型,有点像迭代器)。上面的文章可读性很强,所以我建议大家看一看
gasche提到的“香蕉”论文详细介绍了褶皱的种类及其等效性
最后,还有Bird and Moor's,其中提到了一些转换,如。如果您有兴趣深入了解理论,我建议您阅读一些关于和的内容。虽然围绕它的范畴理论似乎有点吓人,但这个概念并没有那么难 反同构是使用递归数据结构并产生某种值的函数。同构是指给定某个值(一种种子)的函数生成递归数据结构。特别是,在其他Anwer中提到的
foldr
和build
是在列表上构建反同构和反同构的函数。但这个概念基本上可以应用于任何递归数据结构,如不同类型的树等
现在,如果你用一个反同态构建一个递归数据结构,然后用一个反同态使用它,你会得到所谓的hylomorphim。在这种情况下,实际上不需要中间结构。您可以跳过创建和销毁它。这通常被称为
关于
map
:这个函数很有趣,它既是一个反态射又是一个反态射:
使用一个列表并生成一些东西;而且map
生成一个列表,消耗一些东西map
map f。map g
作为一个变形(map g
)与一个变形(map f
)的组合,形成一个hylomorphic。因此,您知道可以通过不创建中间列表来优化(去叶)
具体来说:您可以用两种方式编写map
,一种是使用foldr
,另一种是使用build
:
mapAna :: (a -> b) -> [a] -> [b]
mapAna f xs = build (mapAna' f xs)
mapAna' :: (a -> b) -> [a] -> (b -> c -> c) -> c -> c
mapAna' f [] cons nil = nil
mapAna' f (x : xs) cons nil = (f x) `cons` (mapAna' f xs cons nil)
mapCata :: (a -> b) -> [a] -> [b]
mapCata f xs = foldr (\x ys -> f x : ys) [] xs
而构图
map f(map g zs)
asmapCata f(mapAna g zs)
,经过一些简化并应用foldr c n(build g)==gcn
后,会产生map(f.g)
,您可能想在理论CS页面上发布这一点,too@blueberryfields:用于研究级TCS,这个问题不是@Yttril:Fold是一种通用运算(数据结构上的每个顺序动作都可以表示为Fold),这表明很少有这样的方程成立。@Giles:是的,这就是为什么我想知道到底有多少优化。据我所知,融合需要更高阶的多态递归,虽然我的语言几乎无法支持单子,但它无法处理融合;(可能我这里的一些术语搞错了。…+1用于流融合论文的引用!没有多态递归。我不知道什么是高阶多态递归。但是,build
有一个秩2类型(第一个参数上的forall
)。流融合反过来需要存在类型(步进函数).也许你可以解释一下你想做什么(以及你的设置)?我的设置是我的语言Felix。我主要是在寻找优化。理想情况下,有人会帮助设计一个合适的火种系统,以实现像fusion这样的高级优化。对不起,太简单了:Felix有类型模式,加上一些实现不好的火种,允许实现一些更高的东西,例如Monads..但仅限于类型系统基本上是lambda演算,有产品、函数和类型匹配,但没有变体。如果可以添加变体,我认为它相当于Jay的模式演算的类型化版本。哎哟……折叠在地图上,没想到:)是的,我应该读更多。最近又回到慈善机构。