Функция map

=> CREATE FUNCTION map(a INOUT float[], func text) AS $$
DECLARE
    i integer;
    x float;
BEGIN
    IF cardinality(a) > 0 THEN
        FOR i IN array_lower(a,1)..array_upper(a,1) LOOP
            EXECUTE 'SELECT '||func||'($1)' USING a[i] INTO x;
            a[i] := x;
        END LOOP;
    END IF;
END;
$$ IMMUTABLE LANGUAGE plpgsql;
CREATE FUNCTION
=> SELECT map(ARRAY[4.0,9.0,16.0],'sqrt');
   map   
---------
 {2,3,4}
(1 row)

=> SELECT map(ARRAY[]::float[],'sqrt');
 map 
-----
 {}
(1 row)

Другой вариант реализации с циклом FOREACH:

=> CREATE OR REPLACE FUNCTION map(a float[], func text) RETURNS float[] AS $$
DECLARE
    x float;
    b float[]; -- пустой массив
BEGIN
    FOREACH x IN ARRAY a LOOP
        EXECUTE 'SELECT '||func||'($1)' USING x INTO x;
        b := b || x;
    END LOOP;
    RETURN b;
END;
$$ IMMUTABLE LANGUAGE plpgsql;
CREATE FUNCTION
=> SELECT map(ARRAY[4.0,9.0,16.0],'sqrt');
   map   
---------
 {2,3,4}
(1 row)

=> SELECT map(ARRAY[]::float[],'sqrt');
 map 
-----
 
(1 row)

Функция reduce

=> CREATE FUNCTION reduce(a float[], func text) RETURNS float AS $$
DECLARE
    i integer;
    r float := NULL;
BEGIN
    IF cardinality(a) > 0 THEN
        r := a[array_lower(a,1)];
        FOR i IN array_lower(a,1)+1 .. array_upper(a,1) LOOP
            EXECUTE 'SELECT '||func||'($1,$2)' USING r, a[i] INTO r;
        END LOOP;
    END IF;
    RETURN r;
END;
$$ IMMUTABLE LANGUAGE plpgsql;
CREATE FUNCTION
=> SELECT reduce( ARRAY[1.0,3.0,2.0], 'greatest');
 reduce 
--------
      3
(1 row)

=> SELECT reduce( ARRAY[1.0], 'greatest');
 reduce 
--------
      1
(1 row)

=> SELECT reduce( ARRAY[]::float[], 'greatest');
 reduce 
--------
       
(1 row)

Вариант с циклом FOREACH:

=> CREATE OR REPLACE FUNCTION reduce(a float[], func text) RETURNS float AS $$
DECLARE
    x float;
    r float;
    first boolean := true;
BEGIN
    FOREACH x IN ARRAY a LOOP
        IF first THEN
            r := x;
            first := false;
        ELSE
            EXECUTE 'SELECT '||func||'($1,$2)' USING r, x INTO r;
        END IF;
    END LOOP;
    RETURN r;
END;
$$ IMMUTABLE LANGUAGE plpgsql;
CREATE FUNCTION
=> SELECT reduce( ARRAY[1.0,3.0,2.0], 'greatest');
 reduce 
--------
      3
(1 row)

=> SELECT reduce( ARRAY[1.0], 'greatest');
 reduce 
--------
      1
(1 row)

=> SELECT reduce( ARRAY[]::float[], 'greatest');
 reduce 
--------
       
(1 row)

Полиморфный вариант map

=> DROP FUNCTION map(float[],text);
DROP FUNCTION
=> CREATE FUNCTION map(a anyarray, func text, elem anyelement DEFAULT NULL)
RETURNS anyarray AS $$
DECLARE
    x elem%TYPE;
    b a%TYPE;
BEGIN
    FOREACH x IN ARRAY a LOOP
        EXECUTE 'SELECT '||func||'($1)' USING x INTO x;
        b := b || x;
    END LOOP;
    RETURN b;
END;
$$ IMMUTABLE LANGUAGE plpgsql;
CREATE FUNCTION
=> SELECT map(ARRAY[4.0,9.0,16.0],'sqrt');
                           map                           
---------------------------------------------------------
 {2.000000000000000,3.000000000000000,4.000000000000000}
(1 row)

=> SELECT map(ARRAY[]::float[],'sqrt');
 map 
-----
 
(1 row)

Пример вызова с другим типом данных:

=> SELECT map(ARRAY[' a ','  b','c  '],'btrim');
   map   
---------
 {a,b,c}
(1 row)

Полиморфный вариант reduce

=> DROP FUNCTION reduce(float[],text);
DROP FUNCTION
=> CREATE FUNCTION reduce(a anyarray, func text, elem anyelement DEFAULT NULL) RETURNS anyelement AS $$
DECLARE
    x elem%TYPE;
    r elem%TYPE;
    first boolean := true;
BEGIN
    FOREACH x IN ARRAY a LOOP
        IF first THEN
            r := x;
            first := false;
        ELSE
            EXECUTE 'SELECT '||func||'($1,$2)' USING r, x INTO r;
        END IF;
    END LOOP;
    RETURN r;
END;
$$ IMMUTABLE LANGUAGE plpgsql;
CREATE FUNCTION
=> CREATE FUNCTION add(x anyelement, y anyelement) RETURNS anyelement AS $$
BEGIN
    RETURN x + y;
END;
$$ IMMUTABLE LANGUAGE plpgsql;
CREATE FUNCTION
=> SELECT reduce( ARRAY[1,-2,4], 'add');
 reduce 
--------
      3
(1 row)

=> SELECT reduce( ARRAY['a','b','c'],'concat');
 reduce 
--------
 abc
(1 row)