aboutsummaryrefslogtreecommitdiff
path: root/src/fold.zig
blob: 6b910d3da084ee5bd1c945d789f5b9166914f63b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
const std = @import("std");
const typeVerify = @import("util.zig").typeVerify;

/// ```zig
/// (fn (fn (fn (b, a) b, b, []a) void)
/// ```
/// Folds a list of items over a function with the accumulator as the first arg
/// Type signature: `(b -> a -> b) -> b -> [a] -> b`
/// `func` is of type `b -> a -> b`, where `items` is of type `[a]` and `accumulator` is of type `b`.
/// Haskell equivalent: `foldl func accumulator items`
pub fn foldl(
    comptime func: anytype,
    accumulator: (typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".params[0].type.?),
    items: ([]typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".params[1].type.?),
) typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".return_type.? {
    var accum_internal = accumulator;
    for(items) |i|
        accum_internal = func(accum_internal, i);
    return accum_internal;
}

/// ```zig
/// (fn (fn (fn (a, b) b, b, []a) void)
/// ```
/// Folds a list of items over a function with the accumulator as the second arg
/// Type signature: `(a -> b -> b) -> b -> [a] -> b`
/// `func` is of type `a -> b -> b`, where `items` is of type `[a]` and `accumulator` is of type `b`.
/// Haskell equivalent: `foldr func accumulator items`
pub fn foldr(
    comptime func: anytype,
    accumulator: (typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".params[1].type.?),
    items: ([]typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".params[0].type.?),
) typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".return_type.? {
    var accum_internal = accumulator;
    for(items) |i|
        accum_internal = func(i, accum_internal);
    return accum_internal;
}

/// Variant of `foldl` where the first element is the base case
pub fn foldl1(
    comptime func: anytype,
    items: ([]typeVerify(@TypeOf(func), .{.@"fn"}).@"fn".params[0].type.?)
) typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".return_type.? {
    return foldl(func, items[0], items);
}

/// Variant of `foldr` where the first element is the base case
pub fn foldr1(
    comptime func: anytype,
    items: ([]typeVerify(@TypeOf(func), .{.@"fn"}).@"fn".params[0].type.?)
) typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".return_type.? {
    return foldr(func, items[0], items);
}