Catamorphism

From Rosetta Code
Revision as of 01:54, 30 September 2012 by rosettacode>Spoon! (added ocaml)
Catamorphism is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Reduce is a function or method that is used to take the values in an array or a list and apply a function to successive members of the list to produce (or reduce them to), a single value.

Show how reduce (or foldl or foldr etc), work in your language.

Cf.

C#

<lang csharp>var nums = Enumerable.Range(1, 10);

int summation = nums.Aggregate((a, b) => a + b);

int product = nums.Aggregate((a, b) => a * b);

string concatenation = nums.Aggregate(String.Empty, (a, b) => a.ToString() + b.ToString());

Console.WriteLine("{0} {1} {2}", summation, product, concatenation);</lang>

D

<lang d>import std.stdio, std.algorithm, std.range, std.numeric,

      std.conv, std.typecons, std.typetuple;

void main() {

   auto list = iota(1, 11);
   alias TypeTuple!(q{a + b}, q{a * b}, min, max, gcd) ops;
   foreach (op; ops)
       writeln(op.stringof, ": ", list.reduce!op());
   // std.algorithm.reduce supports multiple functions in parallel:
   reduce!(ops[0], ops[3], text)(tuple(0, 0.0, ""), list).writeln();

}</lang>

Output:
"a + b": 55
"a * b": 3628800
min(T1,T2,T...) if (is(typeof(a < b))): 1
max(T1,T2,T...) if (is(typeof(a < b))): 10
gcd(T): 1
Tuple!(int,double,string)(55, 10, "12345678910")

JavaScript

<lang javascript>var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

function add(a, b) {

   return a + b;

}

var summation = nums.reduce(add);

function mul(a, b) {

   return a * b;

}

var product = nums.reduce(mul, 1);

var concatenation = nums.reduce(add, "");

console.log(summation, product, concatenation);</lang>

OCaml

<lang ocaml># let nums = [1;2;3;4;5;6;7;8;9;10];; val nums : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]

  1. let sum = List.fold_left (+) 0 nums;;

val sum : int = 55

  1. let product = List.fold_left ( * ) 0 nums;;

val product : int = 0</lang>

Perl 6

Any associative infix operator, either built-in or user-defined, may be turned into a reduce operator by putting it into square brackets (known as "the reduce metaoperator") and using it as a list operator. The operations will work left-to-right or right-to-left automatically depending on the natural associativity of the base operator. <lang perl6>my @list = 1..10; say [+] @list; say [*] @list; say [~] @list; say [min] @list; say [max] @list; say [lcm] @list;</lang>

Output:
55
3628800
12345678910
1
10
2520

In addition to the reduce metaoperator, a general higher-order function, reduce, can apply any appropriate function. Reproducing the above in this form, using the function names of those operators, we have: <lang perl6>say reduce &infix:<+>, @list; say reduce &infix:<*>, @list; say reduce &infix:<~>, @list; say reduce &infix:<min>, @list; say reduce &infix:<max>, @list; say reduce &infix:<lcm>, @list;</lang>

Python

<lang python>>>> from operator import add >>> listoflists = [['the', 'cat'], ['sat', 'on'], ['the', 'mat']] >>> help(reduce) Help on built-in function reduce in module __builtin__:

reduce(...)

   reduce(function, sequence[, initial]) -> value
   
   Apply a function of two arguments cumulatively to the items of a sequence,
   from left to right, so as to reduce the sequence to a single value.
   For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
   ((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
   of the sequence in the calculation, and serves as a default when the
   sequence is empty.

>>> reduce(add, listoflists, []) ['the', 'cat', 'sat', 'on', 'the', 'mat'] >>> </lang>

Additional example

<lang python>from functools import reduce from operator import add, mul

nums = range(1,11)

summation = reduce(add, nums)

product = reduce(mul, nums)

concatenation = reduce(lambda a, b: str(a) + str(b), nums)

print(summation, product, concatenation)</lang>