functional programming - What is an anamorphism, and how does one look like in C#? -
i trying wrap head around concept of anamorphism.
in functional programming, anamorphism generalization of concept of unfolds on lists. formally, anamorphisms generic functions can corecursively construct result of type , parameterized functions determine next single step of construction.
its dual, catamorphism, nicely described in post: what catamorphism , can implemented in c# 3.0?.
a nice example of catamorphic behavior in c# linq's aggregate method.
what anamorphic equivalent be? correct think of pseudo-random number generator random anamorphic construct or should process of unfolding include accumulator function 1 below (code snippet taken intro rx)?
ienumerable<t> unfold<t>(t seed, func<t, t> accumulator) { var nextvalue = seed; while (true) { yield return nextvalue; nextvalue = accumulator(nextvalue); } }
linq's aggregate method has signature
t aggregate<t>(ienumerable<t> source, func<t, t, t> accumulator) so corresponding unfolding be
ienumerable<t> unfold<t>(t seed, func<t, nullable<t>> accumulator) { nullable<t> nextvalue = new nullable<t>(seed); while (nextvalue.hasvalue) { yield return nextvalue.value; nextvalue = accumulator(nextvalue); } } in pure functional programming, folding , unfolding must include deterministic function. c#'s system.random, true if consider deterministic internals implicit function, suggest. 1 recreate precise prng using unfold, may not use folding functionally , semantically equivalent fold.
the 2 folding , unfolding of lists above special cases of more general folding of lists:
b fold<a, b>(func<a, b, b> acc, b seed, ienumerable<a> source); ienumerable<b> unfold<a, b>(func<a, nullable<tuple<a, b>>> acc, seed); in linq, generality present in other combinators such select.
as brian's answer question what catamorphism , can implemented in c# 3.0?:
catamorphisms in general refer pattern of folding arbitrary data type.
likewise, 1 may construct anamorphisms on binary trees in c#:
public class tree<t> { public t data { get; private set; } public tree<t> left { get; private set; } public tree<t> right { get; private set; } public tree(t data, tree<t> left, tree<t> right) { this.data = data; this.left = left; this.right = right; } } public struct triple<t> { public t result; public nullable<t> leftseed; public nullable<t> rightseed; } public static tree<t> unfold<t>(func<t, triple<t>> water, t seed) { triple<t> tmp = water(seed); tree<t> lefttree = null; tree<t> righttree = null; if (tmp.leftseed.hasvalue) lefttree = unfold<t>(water, tmp.leftseed.value); if (tmp.rightseed.hasvalue) righttree = unfold<t>(water, tmp.rightseed.value); return new tree(tmp.result, lefttree, righttree); } here rather silly example of how build collatz numbers in this xkcd strip:
public static tree<int> collatztree(int max) { return unfold<int>(i => { if (i >= max) return new triple(i, null, null); int? tpo = (i - 1) % 3 == 0 ? (i - 1) / 3 : null; return new triple(i, tpo, 2*i); }, max); } here heteronormative example of building family tree:
public static tree<person> familytree(person youngestperson) { return unfold<person>(child => { person mother = getmotherfromdatabase(child); person father = getfatherfromdatabase(child); return new triple(p, mother, father); }, youngestperson); } i didn't run of code above there may errors.
Comments
Post a Comment