In functional programming, fold (also termed reduce, accumulate, aggregate, compress, or inject) refers to a family of higher-order functions that analyze a recursive data structure and through use of a given combining operation, recombine the results of recursively processing its constituent parts, building up a return value. Typically, a fold is presented with a combining function, a top node of a data structure, and possibly some default values to be used under certain conditions. The fold then proceeds to combine elements of the data structure's hierarchy, using the function in a systematic way.
Folds are in a sense dual to unfolds, which take a seed value and apply a function corecursively to decide how to progressively construct a corecursive data structure, whereas a fold recursively breaks that structure down, replacing it with the results of applying a combining function at each node on its terminal values and the recursive results (catamorphism, versus anamorphism of unfolds).
Folds can be regarded as consistently replacing the structural components of a data structure with functions and values. Lists, for example, are built up in many functional languages from two primitives: any list is either an empty list, commonly called nil ([]
), or is constructed by prefixing an element in front of another list, creating what is called a cons node ( Cons(X1,Cons(X2,Cons(...(Cons(Xn,nil)))))
), resulting from application of a cons
function (written down as a colon (:)
in Haskell). One can view a fold on lists as replacing the nil at the end of the list with a specific value, and replacing each cons with a specific function. These replacements can be viewed as a diagram:
There's another way to perform the structural transformation in a consistent manner, with the order of the two links of each node flipped when fed into the combining function:
These pictures illustrate right and left fold of a list visually. They also highlight the fact that foldr (:) []
is the identity function on lists (a shallow copy in Lisp parlance), as replacing cons with cons
and nil with nil
will not change the result. The left fold diagram suggests an easy way to reverse a list, foldl (flip (:)) []
. Note that the parameters to cons must be flipped, because the element to add is now the right hand parameter of the combining function. Another easy result to see from this vantage-point is to write the higher-order map function in terms of foldr
, by composing the function to act on the elements with cons
, as:
mapf=foldr((:).f)[]
where the period (.) is an operator denoting function composition.
This way of looking at things provides a simple route to designing fold-like functions on other algebraic data types and structures, like various sorts of trees. One writes a function which recursively replaces the constructors of the datatype with provided functions, and any constant values of the type with provided values. Such a function is generally referred to as a catamorphism.
The folding of the list [1,2,3,4,5]
with the addition operator would result in 15, the sum of the elements of the list [1,2,3,4,5]
. To a rough approximation, one can think of this fold as replacing the commas in the list with the + operation, giving 1 + 2 + 3 + 4 + 5
. [1]
In the example above, + is an associative operation, so the final result will be the same regardless of parenthesization, although the specific way in which it is calculated will be different. In the general case of non-associative binary functions, the order in which the elements are combined may influence the final result's value. On lists, there are two obvious ways to carry this out: either by combining the first element with the result of recursively combining the rest (called a right fold), or by combining the result of recursively combining all elements but the last one, with the last element (called a left fold). This corresponds to a binary operator being either right-associative or left-associative, in Haskell's or Prolog's terminology. With a right fold, the sum would be parenthesized as 1 + (2 + (3 + (4 + 5)))
, whereas with a left fold it would be parenthesized as (((1 + 2) + 3) + 4) + 5
.
In practice, it is convenient and natural to have an initial value which in the case of a right fold is used when one reaches the end of the list, and in the case of a left fold is what is initially combined with the first element of the list. In the example above, the value 0 (the additive identity) would be chosen as an initial value, giving 1 + (2 + (3 + (4 + (5 + 0))))
for the right fold, and ((((0 + 1) + 2) + 3) + 4) + 5
for the left fold. For multiplication, an initial choice of 0 wouldn't work: 0 * 1 * 2 * 3 * 4 * 5 = 0
. The identity element for multiplication is 1. This would give us the outcome 1 * 1 * 2 * 3 * 4 * 5 = 120 = 5!
.
The use of an initial value is necessary when the combining function f is asymmetrical in its types (e.g. a → b → b
), i.e. when the type of its result is different from the type of the list's elements. Then an initial value must be used, with the same type as that of f 's result, for a linear chain of applications to be possible. Whether it will be left- or right-oriented will be determined by the types expected of its arguments by the combining function. If it is the second argument that must be of the same type as the result, then f could be seen as a binary operation that associates on the right, and vice versa.
When the function is a magma, i.e. symmetrical in its types (a → a → a
), and the result type is the same as the list elements' type, the parentheses may be placed in arbitrary fashion thus creating a binary tree of nested sub-expressions, e.g., ((1 + 2) + (3 + 4)) + 5
. If the binary operation f is associative this value will be well-defined, i.e., same for any parenthesization, although the operational details of how it is calculated will be different. This can have significant impact on efficiency if f is non-strict.
Whereas linear folds are node-oriented and operate in a consistent manner for each node of a list, tree-like folds are whole-list oriented and operate in a consistent manner across groups of nodes.
One often wants to choose the identity element of the operation f as the initial value z. When no initial value seems appropriate, for example, when one wants to fold the function which computes the maximum of its two parameters over a non-empty list to get the maximum element of the list, there are variants of foldr
and foldl
which use the last and first element of the list respectively as the initial value. In Haskell and several other languages, these are called foldr1
and foldl1
, the 1 making reference to the automatic provision of an initial element, and the fact that the lists they are applied to must have at least one element.
These folds use type-symmetrical binary operation: the types of both its arguments, and its result, must be the same. Richard Bird in his 2010 book proposes [2] "a general fold function on non-empty lists" foldrn
which transforms its last element, by applying an additional argument function to it, into a value of the result type before starting the folding itself, and is thus able to use type-asymmetrical binary operation like the regular foldr
to produce a result of type different from the list's elements type.
Using Haskell as an example, foldl
and foldr
can be formulated in a few equations.
foldl::(b->a->b)->b->[a]->bfoldlfz[]=zfoldlfz(x:xs)=foldlf(fzx)xs
If the list is empty, the result is the initial value. If not, fold the tail of the list using as new initial value the result of applying f to the old initial value and the first element.
foldr::(a->b->b)->b->[a]->bfoldrfz[]=zfoldrfz(x:xs)=fx(foldrfzxs)
If the list is empty, the result is the initial value z. If not, apply f to the first element and the result of folding the rest.
Lists can be folded over in a tree-like fashion, both for finite and for indefinitely defined lists:
foldtfz[]=zfoldtfz[x]=fxzfoldtfzxs=foldtfz(pairsfxs)foldifz[]=zfoldifz(x:xs)=fx(foldifz(pairsfxs))pairsf(x:y:t)=fxy:pairsftpairs_t=t
In the case of foldi
function, to avoid its runaway evaluation on indefinitely defined lists the function f
must not always demand its second argument's value, at least not all of it, or not immediately (see example below).
foldl1f[x]=xfoldl1f(x:y:xs)=foldl1f(fxy:xs)foldr1f[x]=xfoldr1f(x:xs)=fx(foldr1fxs)foldt1f[x]=xfoldt1f(x:y:xs)=foldt1f(fxy:pairsfxs)foldi1f[x]=xfoldi1f(x:xs)=fx(foldi1f(pairsfxs))
In the presence of lazy, or non-strict evaluation, foldr
will immediately return the application of f to the head of the list and the recursive case of folding over the rest of the list. Thus, if f is able to produce some part of its result without reference to the recursive case on its "right" i.e., in its second argument, and the rest of the result is never demanded, then the recursion will stop (e.g., head==foldr(\ab->a)(error"empty list")
). This allows right folds to operate on infinite lists. By contrast, foldl
will immediately call itself with new parameters until it reaches the end of the list. This tail recursion can be efficiently compiled as a loop, but can't deal with infinite lists at all — it will recurse forever in an infinite loop.
Having reached the end of the list, an expression is in effect built by foldl
of nested left-deepening f
-applications, which is then presented to the caller to be evaluated. Were the function f
to refer to its second argument first here, and be able to produce some part of its result without reference to the recursive case (here, on its left i.e., in its first argument), then the recursion would stop. This means that while foldr
recurses on the right, it allows for a lazy combining function to inspect list's elements from the left; and conversely, while foldl
recurses on the left, it allows for a lazy combining function to inspect list's elements from the right, if it so chooses (e.g., last==foldl(\ab->b)(error"empty list")
).
Reversing a list is also tail-recursive (it can be implemented using rev=foldl(\ysx->x:ys)[]
). On finite lists, that means that left-fold and reverse can be composed to perform a right fold in a tail-recursive way (cf. 1+>(2+>(3+>0))==((0<+3)<+2)<+1
), with a modification to the function f
so it reverses the order of its arguments (i.e., foldrfz==foldl(flipf)z.foldl(flip(:))[]
), tail-recursively building a representation of expression that right-fold would build. The extraneous intermediate list structure can be eliminated with the continuation-passing style technique, foldrfzxs==foldl(\kx->k.fx)idxsz
; similarly, foldlfzxs==foldr(\xk->k.flipfx)idxsz
( flip
is only needed in languages like Haskell with its flipped order of arguments to the combining function of foldl
unlike e.g., in Scheme where the same order of arguments is used for combining functions to both foldl
and foldr
).
Another technical point is that, in the case of left folds using lazy evaluation, the new initial parameter is not being evaluated before the recursive call is made. This can lead to stack overflows when one reaches the end of the list and tries to evaluate the resulting potentially gigantic expression. For this reason, such languages often provide a stricter variant of left folding which forces the evaluation of the initial parameter before making the recursive call. In Haskell this is the foldl'
(note the apostrophe, pronounced 'prime') function in the Data.List
library (one needs to be aware of the fact though that forcing a value built with a lazy data constructor won't force its constituents automatically by itself). Combined with tail recursion, such folds approach the efficiency of loops, ensuring constant space operation, when lazy evaluation of the final result is impossible or undesirable.
Using a Haskell interpreter, the structural transformations which fold functions perform can be illustrated by constructing a string:
λ>foldr(\xy->concat["(",x,"+",y,")"])"0"(mapshow[1..13])"(1+(2+(3+(4+(5+(6+(7+(8+(9+(10+(11+(12+(13+0)))))))))))))"λ>foldl(\xy->concat["(",x,"+",y,")"])"0"(mapshow[1..13])"(((((((((((((0+1)+2)+3)+4)+5)+6)+7)+8)+9)+10)+11)+12)+13)"λ>foldt(\xy->concat["(",x,"+",y,")"])"0"(mapshow[1..13])"(((((1+2)+(3+4))+((5+6)+(7+8)))+(((9+10)+(11+12))+13))+0)"λ>foldi(\xy->concat["(",x,"+",y,")"])"0"(mapshow[1..13])"(1+((2+3)+(((4+5)+(6+7))+((((8+9)+(10+11))+(12+13))+0))))"
Infinite tree-like folding is demonstrated e.g., in recursive primes production by unbounded sieve of Eratosthenes in Haskell:
primes=2:_Y((3:).minus[5,7..].foldi(\(x:xs)ys->x:unionxsys)[].map(\p->[p*p,p*p+2*p..]))_Yg=g(_Yg)-- = g . g . g . g . ...
where the function union
operates on ordered lists in a local manner to efficiently produce their set union, and minus
their set difference.
A finite prefix of primes is concisely defined as a folding of set difference operation over the lists of enumerated multiples of integers, as
primesTon=foldl1minus[[2*x,3*x..n]|x<-[1..n]]
For finite lists, e.g., merge sort (and its duplicates-removing variety, nubsort
) could be easily defined using tree-like folding as
mergesortxs=foldtmerge[][[x]|x<-xs]nubsortxs=foldtunion[][[x]|x<-xs]
with the function merge
a duplicates-preserving variant of union
.
Functions head
and last
could have been defined through folding as
head=foldr(\xr->x)(error"head: Empty list")last=foldl(\ax->x)(error"last: Empty list")
Language | Left fold | Right fold | Left fold without initial value | Right fold without initial value | Unfold | Notes |
---|---|---|---|---|---|---|
APL | func⍨/⌽initval,vector | func/vector,initval | func⍨/⌽vector | func/vector | ||
C# 3.0 | ienum | ienum.Reverse() | ienum | ienum.Reverse() | Aggregate is an extension method ienum is an IEnumerable<T> Similarly in all .NET languages | |
C++ | std::accumulate( | std::accumulate( | in header <numeric> begin , end , rbegin , rend are iteratorsfunc can be a function pointer or a function object | |||
C++17 | (initvalop ... oppack) | (packop ... opinitval) | (... oppack) | (packop ...) | Fold expression (only for variadic templates): op is a binary operator (both op s must be the same, e.g., (std::cout<<...<<args) ), pack is an unexpanded parameter pack. | |
C++23 | std::ranges::fold_left(range, initval, func) | std::ranges::fold_right(range, initval, func) | std::ranges::fold_left_first(range, func) | std::ranges::fold_right_last(range, func) | Both std::ranges::fold_left_first and std::ranges::fold_right_last return std::optional considering the emptiness of range . | |
CFML | obj.reduce(func, initial) | obj.reduce(func) | Where func receives as arguments the result of the previous operation (or the initial value on the first iteration); the current item; the current item's index or key; and a reference to the obj | |||
Clojure | (reduce funcinitvallist) | (reduce funcinitval (reverse list)) | (reduce funclist) | (reduce func (reverse list)) | See also clojure.core.reducers/fold | |
Common Lisp | (reduce funclist :initial-value initval) | (reduce funclist :from-end t :initial-value initval) | (reduce funclist) | (reduce funclist :from-end t) | ||
D | reduce!func(initval, list) | reduce!func(initval, list | reduce!func(list) | reduce!func( | in module std.algorithm | |
Elixir | List.foldl(list, acc, fun) | List.foldr(list, acc, fun) | See documentation for example usage | |||
Elm | List.foldl(Fun, Accumulator, List) | List.foldr(Fun, Accumulator, List) | See also List API | |||
Erlang | lists:foldl(Fun, Accumulator, List) | lists:foldr(Fun, Accumulator, List) | ||||
F# | List.fold funcinitvallist Seq.fold funcinitvalsequence | List.foldBack funclistinitval | List.reduce funclist Seq.reduce funcsequence | List.reduceBack funclist | Seq.unfold funcinitval | |
Gleam | list.fold(list, initial, func) iterator.fold(iterator, initial, func | list.fold_right(list, initial, func) | list.reduce(list, func) iterator.reduce(iterator, func) | iterator.unfold(initial, func) | ||
Gosu | Iterable.fold(f(agg, e)) Iterable.reduce(init, f(agg, e)) Iterable.partition(f(e)) | All are extension methods on Java's Iterable interface, arrays are also supported | ||||
Groovy | list | list.reverse() | list | list.reverse() | ||
Haskell | foldl funcinitvallist | foldr funcinitvallist | foldl1 funclist | foldr1 funclist | unfoldr funcinitval | For foldl , the folding function takes arguments in the opposite order as that for foldr . |
Haxe | Lambda.fold(iterable, func, initval) | |||||
J | verb~/|.initval,array | verb/ array,initval | verb~/|.array | verb/ array | u/y applies the dyad u between the items of y. "J Dictionary: Insert" | |
Java 8+ | stream.reduce | stream.reduce | ||||
JavaScript 1.8 ECMAScript 5 | array.reduce [3] | array.reduceRight(func,initVal) | array.reduce | array.reduceRight(func) | The reducer main arguments are accumulator and current value, and we can use optional arguments like index and array. array.reduceRight((acc,value, idx, array)=>{}, initvalue) | |
Julia | foldl(op, itr; [init]) | foldr(op, itr; [init]) | foldl(op, itr) | foldr(op, itr) | ||
Kotlin | Iterable.fold | Iterable.foldRight | Iterable.reduce(func) | Iterable.reduceRight(func) | Other collections also support fold [4] and reduce . [5] There is also Result.fold(onSuccess, onFailure) , [6] which reduces a Result<T> (either success or failure) to the return type of onSuccess and onFailure . | |
LFE | (lists:foldl funcaccumlist) | (lists:foldr funcaccumlist) | ||||
Logtalk | fold_left(Closure, Initial, List, Result) | fold_right(Closure, Initial, List, Result) | Meta-predicates provided by the meta standard library object. The abbreviations foldl and foldr may also be used. | |||
Maple | foldl(func, initval, sequence) | foldr(func, initval, sequence) | foldl(func, sequence) | foldr(func, sequence) | ||
Mathematica | Fold[func, initval, list] | Fold[func, initval, Reverse[list]] | Fold[func, list] | Fold[func, Reverse[list]] | NestWhileList[func,, initval, predicate] | Fold without an initial value is supported in versions 10.0 and higher. |
MATLAB | fold(@func, list, defaultVal) | fold(@func, flip(list), defaultVal) | fold(@func, list) | fold(@func, flip(list)) |
| Requires Symbolic Math Toolbox, supported from R2016b. |
Maxima | lreduce(func, list, initval) | rreduce(func, list, initval) | lreduce(func, list) | rreduce(func, list) | ||
OCaml | List.fold_left funcinitvallist Array.fold_left funcinitvalarray | List.fold_right funclistinitval Array.fold_right funcarrayinitval | ||||
Oz | {FoldL ListFuncInitVal} | {FoldR ListFuncInitVal} | ||||
PARI/GP | fold( f, A ) | |||||
Perl | reduce blockinitval, list | reduce blocklist | in List::Util module | |||
PHP | array_reduce(array, func, initval) | array_reduce( | array_reduce(array, func) | array_reduce( | When initval is not supplied, NULL is used, so this is not a true foldl1. Before PHP 5.3, initval can only be integer. func is a callback Archived 2020-11-28 at the Wayback Machine . Try array_reduce online. | |
Python 2.x | reduce(func, list, initval) | reduce(lambda x, y: func(y, x), reversed(list), initval) | reduce(func, list) | reduce(lambda x, y: func(y, x), reversed(list)) | ||
Python 3.x | functools.reduce(func, list, initval) | functools.reduce(lambda x, y: func(y, x), reversed(list), initval) | functools.reduce(func, list) | functools.reduce(lambda x, y: func(y, x), reversed(list)) | In module functools. [7] | |
R | Reduce(func, list, initval) | Reduce(func, list, initval, right=TRUE) | Reduce(func, list) | Reduce(func, list, right=TRUE) | R supports right folding and left or right folding with or without an initial value through the right and init arguments to the Reduce function. | |
Racket | (foldl func initval list) | (foldr func initval list) | ||||
Ruby | enum enum | enum.reverse_each enum.reverse_each | enum enum.reduce(&block) | enum.reverse_each enum.reverse_each | In Ruby 1.8.7+, can also pass a symbol representing a function instead of a block.enum is an EnumerationPlease notice that these implementations of right folds are wrong for non-commutative &block (also initial value is put on wrong side). | |
Rust | iterator.fold(initval, func) | iterator.rev().fold(initval, func) | iterator.reduce(func) | iterator.rev().reduce(func) | iterator.rev() requires iterator to be a DoubleEndedIterator . [8] | |
Scala | list.foldLeft(initval)(func) (initval /: list)(func) | list.foldRight(initval)(func) (list :\ initval)(func) | list.reduceLeft(func) | list.reduceRight(func) | Scala's symbolic fold syntax was intended to resemble the left- or right-leaning tree commonly used to explain the fold operation, [9] but has since been reinterpreted as an illustration of a toppling domino. [10] The colon comes from a general Scala syntax mechanism whereby the apparent infix operator is invoked as a method on the left operand with the right operand passed as an argument, or vice versa if the operator's last character is a colon, here applied symmetrically. Scala also features the tree-like folds using the method | |
Scheme R6RS | (fold-left funcinitvallist) (vector-fold funcinitvalvector) | (fold-right funcinitvallist) (vector-fold-right funcinitvalvector) | (reduce-left funcdefaultvallist) | (reduce-right funcdefaultvallist) | (unfold pfgseed[tail-gen]) unfold-right pfgseed[tail] (vector-unfold flengthinitial-seed···) (vector-unfold-right flengthinitial-seed···) | srfi/1 srfi/43 |
Smalltalk | aCollection inject: aValue into: aBlock | aCollection reduce: aBlock | ANSI Smalltalk doesn't define #reduce: but many implementations do. | |||
Standard ML | foldl funcinitvallist Array.foldl funcinitvalarray | foldr funcinitvallist Array.foldr funcinitvalarray | The supplied function takes its arguments in a tuple. For foldl , the folding function takes arguments in the same order as for foldr . | |||
Swift | array.reduce(initval, func) reduce(sequence, initval, func) | array.reverse() | ||||
XPath | fold-left($input, $zero, $action) array:fold-left($input, $zero, $action) | fold-right($input, $zero, $action) array:fold-right($input, $zero, $action) | Two functions exist for each case because XPath offers sequences for unstructured and arrays for structured data. | |||
Xtend | iterable.fold(initval,[func]) | iterable.reduce[func] |
Fold is a polymorphic function. For any g having a definition
g[]=vg(x:xs)=fx(gxs)
then g can be expressed as [12]
g=foldrfv
Also, in a lazy language with infinite lists, a fixed point combinator can be implemented via fold, [13] proving that iterations can be reduced to folds:
yf=foldr(\_->f)undefined(repeatundefined)
ML is a general-purpose, high-level, functional programming language. It is known for its use of the polymorphic Hindley–Milner type system, which automatically assigns the data types of most expressions without requiring explicit type annotations, and ensures type safety; there is a formal proof that a well-typed ML program does not cause runtime type errors. ML provides pattern matching for function arguments, garbage collection, imperative programming, call-by-value and currying. While a general-purpose programming language, ML is used heavily in programming language research and is one of the few languages to be completely specified and verified using formal semantics. Its types and pattern matching make it well-suited and commonly used to operate on other formal languages, such as in compiler writing, automated theorem proving, and formal verification.
Standard ML (SML) is a general-purpose, high-level, modular, functional programming language with compile-time type checking and type inference. It is popular for writing compilers, for programming language research, and for developing theorem provers.
In combinatory logic for computer science, a fixed-point combinator, is a higher-order function that returns some fixed point of its argument function, if one exists.
In computer programming, cons
is a fundamental function in most dialects of the Lisp programming language. cons
constructs memory objects which hold two values or pointers to two values. These objects are referred to as (cons) cells, conses, non-atomic s-expressions ("NATSes"), or (cons) pairs. In Lisp jargon, the expression "to cons x onto y" means to construct a new object with (cons xy)
. The resulting pair has a left half, referred to as the car
, and a right half, referred to as the cdr
.
In computer science, pattern matching is the act of checking a given sequence of tokens for the presence of the constituents of some pattern. In contrast to pattern recognition, the match usually has to be exact: "either it will or will not be a match." The patterns generally have the form of either sequences or tree structures. Uses of pattern matching include outputting the locations of a pattern within a token sequence, to output some component of the matched pattern, and to substitute the matching pattern with some other token sequence.
In computer programming, especially functional programming and type theory, an algebraic data type (ADT) is a kind of composite type, i.e., a type formed by combining other types.
Curry is a declarative programming language, an implementation of the functional logic programming paradigm, and based on the Haskell language. It merges elements of functional and logic programming, including constraint programming integration.
In computer science, a tagged union, also called a variant, variant record, choice type, discriminated union, disjoint union, sum type, or coproduct, is a data structure used to hold a value that could take on several different, but fixed, types. Only one of the types can be in use at any one time, and a tag field explicitly indicates which type is in use. It can be thought of as a type that has several "cases", each of which should be handled correctly when that type is manipulated. This is critical in defining recursive datatypes, in which some component of a value may have the same type as that value, for example in defining a type for representing trees, where it is necessary to distinguish multi-node subtrees and leaves. Like ordinary unions, tagged unions can save storage by overlapping storage areas for each type, since only one is in use at a time.
In computing, a persistent data structure or not ephemeral data structure is a data structure that always preserves the previous version of itself when it is modified. Such data structures are effectively immutable, as their operations do not (visibly) update the structure in-place, but instead always yield a new updated structure. The term was introduced in Driscoll, Sarnak, Sleator, and Tarjan's 1986 article.
In computer science, corecursion is a type of operation that is dual to recursion. Whereas recursion works analytically, starting on data further from a base case and breaking it down into smaller data and repeating until one reaches a base case, corecursion works synthetically, starting from a base case and building it up, iteratively producing data further removed from a base case. Put simply, corecursive algorithms use the data that they themselves produce, bit by bit, as they become available, and needed, to produce further bits of data. A similar but distinct concept is generative recursion, which may lack a definite "direction" inherent in corecursion and recursion.
In computer programming languages, a recursive data type is a data type for values that may contain other values of the same type. Data of recursive types are usually viewed as directed graphs.
In computer science, recursion is a method of solving a computational problem where the solution depends on solutions to smaller instances of the same problem. Recursion solves such recursive problems by using functions that call themselves from within their own code. The approach can be applied to many types of problems, and recursion is one of the central ideas of computer science.
The power of recursion evidently lies in the possibility of defining an infinite set of objects by a finite statement. In the same manner, an infinite number of computations can be described by a finite recursive program, even if this program contains no explicit repetitions.
In mathematics, an initial algebra is an initial object in the category of F-algebras for a given endofunctor F. This initiality provides a general framework for induction and recursion.
In functional programming, the concept of catamorphism denotes the unique homomorphism from an initial algebra into some other algebra.
In computer programming, append
is the operation for concatenating linked lists or arrays in some high-level programming languages.
Tacit programming, also called point-free style, is a programming paradigm in which function definitions do not identify the arguments on which they operate. Instead the definitions merely compose other functions, among which are combinators that manipulate the arguments. Tacit programming is of theoretical interest, because the strict use of composition results in programs that are well adapted for equational reasoning. It is also the natural style of certain programming languages, including APL and its derivatives, and concatenative languages such as Forth. The lack of argument naming gives point-free style a reputation of being unnecessarily obscure, hence the epithet "pointless style".
In many programming languages, map is a higher-order function that applies a given function to each element of a collection, e.g. a list or set, returning the results in a collection of the same type. It is often called apply-to-all when considered in functional form.
In computer programming, an anonymous function is a function definition that is not bound to an identifier. Anonymous functions are often arguments being passed to higher-order functions or used for constructing the result of a higher-order function that needs to return a function. If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function. Anonymous functions are ubiquitous in functional programming languages and other languages with first-class functions, where they fulfil the same role for the function type as literals do for other data types.
In computer programming, an anamorphism is a function that generates a sequence by repeated application of the function to its previous result. You begin with some value A and apply a function f to it to get B. Then you apply f to B to get C, and so on until some terminating condition is reached. The anamorphism is the function that generates the list of A, B, C, etc. You can think of the anamorphism as unfolding the initial value into a sequence.
This article describes the features in the programming language Haskell.
functools.reduce
: import functools
reduce
: from functools import reduce