aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.zig3
-rw-r--r--src/example.zig18
-rw-r--r--src/fold.zig54
-rw-r--r--src/map.zig27
-rw-r--r--src/newLib.zig163
-rw-r--r--src/oldLib.zig227
-rw-r--r--src/root.zig4
7 files changed, 81 insertions, 415 deletions
diff --git a/build.zig b/build.zig
index 5f7d1f1..f1ad78e 100644
--- a/build.zig
+++ b/build.zig
@@ -29,6 +29,9 @@ pub fn build(b: *std.Build) !void {
b.installArtifact(exe);
+ const ir_file = b.addInstallFile(exe.getEmittedLlvmIr(), "output.ll");
+ b.getInstallStep().dependOn(&ir_file.step);
+
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd.addArgs(args);
diff --git a/src/example.zig b/src/example.zig
index cc3d2c8..6622726 100644
--- a/src/example.zig
+++ b/src/example.zig
@@ -20,6 +20,7 @@ fn addThenMultiply(n: i32, m: i32, q: i32) i32 {
pub fn main() !void {
var gpa = std.heap.DebugAllocator(.{}){};
+ defer _=gpa.deinit();
const allocator = gpa.allocator();
// Currying
const curriedAddResult = func.curry(add)(4)(5);
@@ -29,16 +30,27 @@ pub fn main() !void {
// Map
var items = [_]i32{ 0, 1, 2, 3, 4 };
const itemsSlice: []i32 = items[0..items.len];
- const buffer = try func.mapAlloc(allocator, iterThenMul2, itemsSlice);
+ var buffer: [16]i32 = undefined;
+ var buffSlice: []i32 = buffer[0..16];
+ func.map(iterThenMul2, itemsSlice, &buffSlice);
+ const bufferAlloc = try func.mapAlloc(allocator, iterThenMul2, itemsSlice);
+ defer allocator.free(bufferAlloc);
std.debug.print("curry(add)(4)(5) = {any}\n", .{ curriedAddResult });
std.debug.print("compose(mul2, iter)(5) = {d}\n", .{ composed });
- std.debug.print("mapAlloc(allocator, compose(mul2, iter), []i32{{ 0, 1, 2, 3, 4 }}) = {{ ", .{});
+ std.debug.print("map(compose(mul2, iter), []i32{{ 0, 1, 2, 3, 4 }}, buffer); \nbuffer = {{ ", .{});
// func.map(func: anytype, items: anytype, buffer: anytype)
- for(buffer) |item| {
+ for(buffer[0..itemsSlice.len]) |item| {
+ std.debug.print("{d}, ", .{item});
+ }
+ std.debug.print("}}\n", .{});
+
+ std.debug.print("mapAlloc(allocator, compose(mul2, iter), []i32{{ 0, 1, 2, 3, 4 }}) = {{ ", .{});
+ for(bufferAlloc) |item| {
std.debug.print("{d}, ", .{item});
}
std.debug.print("}}\n", .{});
+ std.debug.print("foldl(add, 0, bufferAlloc) = {d}\n", .{func.foldl(add, 0, bufferAlloc)});
std.debug.print("I(5) = {any}\n", .{c.I(5)});
std.debug.print("K(5)(7) = {any}\n", .{c.K(5)(7)});
std.debug.print("(S K S K)(5)(7) = {any}\n", .{((c.S(c.K)(c.S)(c.K))(mul2)(func.curry(add)(3)))(7)});
diff --git a/src/fold.zig b/src/fold.zig
new file mode 100644
index 0000000..6b910d3
--- /dev/null
+++ b/src/fold.zig
@@ -0,0 +1,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);
+}
diff --git a/src/map.zig b/src/map.zig
index c532f9e..b04366d 100644
--- a/src/map.zig
+++ b/src/map.zig
@@ -13,20 +13,9 @@ pub fn map(
items: []typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".params[0].type.?,
buffer: *[]typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".return_type.?,
) void {
- _=typeVerify(@TypeOf(func), .{ .@"fn" });
- // const itemsInfo = typeVerify(@TypeOf(items), .{ .pointer, .array });
- // const bufferInfo = typeVerify(@TypeOf(buffer), .{ .pointer });
- // const bufferChildInfo = typeVerify(bufferInfo.pointer.child, .{ .pointer, .array });
- // switch (itemsInfo) {
- // .pointer => |p| if(p.size != .many and p.size != .slice)
- // @compileError("Expected pointer of size 'many' or 'slice', found '" ++ @tagName(p.size) ++ "'"),
- // else =>{},
- // }
- // switch (bufferChildInfo) {
- // .pointer => |p| if(p.size != .many and p.size != .slice)
- // @compileError("Expected pointer of size 'many' or 'slice', found '" ++ @tagName(p.size) ++ "'"),
- // else =>{},
- // }
+ const fInfo =typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn";
+ if(fInfo.params.len > 1)
+ @compileError("Function passed into map must have exactly one argument");
for (items, 0..) |item, i|
buffer.*[i] = func(item);
}
@@ -35,6 +24,7 @@ pub fn map(
/// (fn (Allocator, fn (fn (a) b, []a) error{OutOfMemory}![]b)
/// ```
/// Map a function onto a list of values, allocating space for the new slice
+/// The return value of this function must be freed using `allocator.free()`
/// Type signature: `(a -> b) -> [a] -> [b]`
/// `func` is of type `a -> b`, where `items` is of type `[a]`.
/// `map` will return a slice of type `[b]`
@@ -42,16 +32,9 @@ pub fn map(
pub fn mapAlloc(
allocator: std.mem.Allocator,
func: anytype,
- items: anytype,
+ items: []typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".params[0].type.?,
) error{OutOfMemory}!blk:{
const funcInfo = typeVerify(@TypeOf(func), .{ .@"fn" });
- const itemsInfo = typeVerify(@TypeOf(items), .{ .array, .pointer });
- switch (itemsInfo) {
- .pointer => |p| if(p.size != .many and p.size != .slice)
- @compileError("Expected pointer of size 'many' or 'slice', found " ++ @tagName(p)),
- else =>{},
- }
-
break :blk []funcInfo.@"fn".return_type.?;
} {
const funcInfo = typeVerify(@TypeOf(func), .{ .@"fn" });
diff --git a/src/newLib.zig b/src/newLib.zig
deleted file mode 100644
index fff975a..0000000
--- a/src/newLib.zig
+++ /dev/null
@@ -1,163 +0,0 @@
-const std = @import("std");
-const Type = std.builtin.Type;
-
-fn typeVerify(T: type, expected: anytype) Type {
- const expectedType = @TypeOf(expected);
- const expectedTypeInfo = @typeInfo(expectedType);
- if (expectedTypeInfo != .@"struct")
- @compileError("Expected struct or tuple, found " ++ @typeName(expectedType));
- const realTypeInfo = @typeInfo(T);
- for (expected) |e| {
- if(realTypeInfo == e) return realTypeInfo;
- }
- for (expected) |e|
- @compileError("Expected one of " ++ @tagName(e) ++ ", found " ++ @typeName(T));
- return realTypeInfo;
-}
-
-/// ```zig
-/// (fn (fn (b) c, fn (a) b) fn (a) c)
-/// ```
-/// Function composition
-/// Type signature: (a -> b) -> (b -> c) -> (a -> c)
-/// `outerFunc` and `innerFunc` are functions of types `b -> c` and `a -> b` respectively
-/// Haskell equivalent: `outerFunc . innerFunc`
-pub fn compose(
- comptime outerFunc: anytype,
- comptime innerFunc: anytype
-) blk:{
- _=typeVerify(@TypeOf(outerFunc), .{ .@"fn" });
- _=typeVerify(@TypeOf(innerFunc), .{ .@"fn" });
- const out = @typeInfo(@TypeOf(outerFunc)).@"fn".return_type.?;
- const in = @typeInfo(@TypeOf(innerFunc)).@"fn".params[0].type.?;
- break :blk fn(in) out;
-} {
- const out = @typeInfo(@TypeOf(outerFunc)).@"fn".return_type.?;
- const in = @typeInfo(@TypeOf(innerFunc)).@"fn".params[0].type.?;
- return struct {
- fn func(input: in) out {
- return outerFunc(innerFunc(input));
- }
- }.func;
-}
-
-/// ```zig
-/// (fn (Allocator, fn (fn (a) b, []a) error{OutOfMemory}![]b)
-/// ```
-/// Map a function onto a list of values, allocating space for the new slice
-/// Type signature: `(a -> b) -> [a] -> [b]`
-/// `func` is of type `a -> b`, where `items` is of type `[a]`.
-/// `map` will return a slice of type `[b]`
-/// Haskell equivalent: `map func items`
-pub fn mapAlloc(
- allocator: std.mem.Allocator,
- func: anytype,
- items: anytype,
-) error{OutOfMemory}!blk:{
- const funcInfo = typeVerify(@TypeOf(func), .{ .@"fn" });
- const itemsInfo = typeVerify(@TypeOf(items), .{ .array, .pointer });
- switch (itemsInfo) {
- .pointer => |p| if(p.size != .many and p.size != .slice)
- @compileError("Expected pointer of size 'many' or 'slice', found " ++ @tagName(p)),
- else =>{},
- }
-
- break :blk []funcInfo.@"fn".return_type.?;
-} {
- const funcInfo = typeVerify(@TypeOf(func), .{ .@"fn" });
- var result = try allocator.alloc(funcInfo.@"fn".return_type.?, items.len);
- for(items, 0..) |item, i|
- result[i] = func(item);
- return result;
-}
-
-/// ```zig
-/// (fn (Allocator, fn (fn (a) b, []a, *[]b) void)
-/// ```
-/// Map a function onto a list of values, using a buffer
-/// Type signature: `(a -> b) -> [a] -> [b]`
-/// `func` is of type `a -> b`, where `items` is of type `[a]` and `buffer` is a pointer to a value of type `[b]`.
-/// Haskell equivalent: `map func items`
-pub fn map(
- func: anytype,
- items: anytype,
- buffer: anytype,
-) void {
- _=typeVerify(@TypeOf(func), .{ .@"fn" });
- const itemsInfo = typeVerify(@TypeOf(items), .{ .pointer, .array });
- const bufferInfo = typeVerify(@TypeOf(buffer), .{ .pointer });
- const bufferChildInfo = typeVerify(bufferInfo.pointer.child, .{ .pointer, .array });
- switch (itemsInfo) {
- .pointer => |p| if(p.size != .many and p.size != .slice)
- @compileError("Expected pointer of size 'many' or 'slice', found '" ++ @tagName(p.size) ++ "'"),
- else =>{},
- }
- switch (bufferChildInfo) {
- .pointer => |p| if(p.size != .many and p.size != .slice)
- @compileError("Expected pointer of size 'many' or 'slice', found '" ++ @tagName(p.size) ++ "'"),
- else =>{},
- }
- for (items, 0..) |item, i|
- buffer.*[i] = func(item);
-}
-
-pub fn curry(func: anytype) curryTypeGetter(@TypeOf(func), @TypeOf(func), .{}) {
- return curryHelper(func, .{});
-}
-
-fn curryTypeGetter(comptime func: type, comptime newfunc: type, comptime args: anytype) type {
- const typeInfo = typeVerify(func, .{ .@"fn" = undefined }).@"fn";
- const newTypeInfo = typeVerify(newfunc, .{ .@"fn" = undefined }).@"fn";
-
- // Base case: if we've curried all but one parameter, return final function type
- if (typeInfo.params.len == args.len + 1) {
- return fn(typeInfo.params[args.len].type.?) typeInfo.return_type.?;
- }
-
- // Recursive case: return function that takes next param and returns curried function
- const nextParamType = typeInfo.params[args.len].type.?;
- var buf: [64]type = undefined;
- for (args, 0..) |a, i| {
- buf[i] = if (@TypeOf(a) != type) @TypeOf(a) else a;
- }
- buf[args.len] = nextParamType;
-
- return fn(nextParamType) curryTypeGetter(func, @Type(.{
- .@"fn" = .{
- .calling_convention = newTypeInfo.calling_convention,
- .is_generic = newTypeInfo.is_generic,
- .params = newTypeInfo.params[1..],
- .is_var_args = newTypeInfo.is_var_args,
- .return_type = newTypeInfo.return_type,
- }
- }), buf[0..args.len+1].*);
-}
-
-fn curryHelper(comptime func: anytype, args: anytype) curryTypeGetter(@TypeOf(func), @TypeOf(func), args) {
- const typeInfo = typeVerify(@TypeOf(func), .{ .@"fn" = undefined }).@"fn";
- const argInfo = @typeInfo(@TypeOf(args)).@"struct";
- _=argInfo;
-
- const nextParamType = typeInfo.params[args.len].type.?;
-
- const Closure = struct {
- fn funcCurry(arg: nextParamType) curryTypeGetter(@TypeOf(func), @TypeOf(func), args).ReturnType {
- // Base case: if we have all arguments, call the function
- if (args.len + 1 == typeInfo.params.len) {
- return @call(.auto, func, args ++ .{arg});
- }
-
- // Recursive case: create new tuple with additional argument
- const newArgs = args ++ .{arg};
- return curryHelper(func, newArgs);
- }
- };
-
- return Closure.funcCurry;
-}
-
-fn intToStringZ(int: u32, buf: []u8) ![:0]u8 {
- return try std.fmt.bufPrintZ(buf, "{}", .{int});
-}
-
-// TODO: Add tests
diff --git a/src/oldLib.zig b/src/oldLib.zig
deleted file mode 100644
index 013daa7..0000000
--- a/src/oldLib.zig
+++ /dev/null
@@ -1,227 +0,0 @@
-const std = @import("std");
-const Type = std.builtin.Type;
-
-fn typeVerify(T: type, expected: anytype) Type {
- const expectedType = @TypeOf(expected);
- const expectedTypeInfo = @typeInfo(expectedType);
- if (expectedTypeInfo != .@"struct")
- @compileError("Expected struct or tuple, found " ++ @typeName(expectedType));
- const realTypeInfo = @typeInfo(T);
- for (expected) |e| {
- if(realTypeInfo == e) return realTypeInfo;
- }
- for (expected) |e|
- @compileError("Expected one of " ++ @tagName(e) ++ ", found " ++ @typeName(T));
- return realTypeInfo;
-}
-
-/// ```zig
-/// (fn (fn (b) c, fn (a) b) fn (a) c)
-/// ```
-/// Function composition
-/// Type signature: (a -> b) -> (b -> c) -> (a -> c)
-/// `outerFunc` and `innerFunc` are functions of types `b -> c` and `a -> b` respectively
-/// Haskell equivalent: `outerFunc . innerFunc`
-pub fn compose(
- comptime outerFunc: anytype,
- comptime innerFunc: anytype
-) blk:{
- _=typeVerify(@TypeOf(outerFunc), .{ .@"fn" });
- _=typeVerify(@TypeOf(innerFunc), .{ .@"fn" });
- const out = @typeInfo(@TypeOf(outerFunc)).@"fn".return_type.?;
- const in = @typeInfo(@TypeOf(innerFunc)).@"fn".params[0].type.?;
- break :blk fn(in) out;
-} {
- const out = @typeInfo(@TypeOf(outerFunc)).@"fn".return_type.?;
- const in = @typeInfo(@TypeOf(innerFunc)).@"fn".params[0].type.?;
- return struct {
- fn func(input: in) out {
- return outerFunc(innerFunc(input));
- }
- }.func;
-}
-
-/// ```zig
-/// (fn (Allocator, fn (fn (a) b, []a) error{OutOfMemory}![]b)
-/// ```
-/// Map a function onto a list of values, allocating space for the new slice
-/// Type signature: `(a -> b) -> [a] -> [b]`
-/// `func` is of type `a -> b`, where `items` is of type `[a]`.
-/// `map` will return a slice of type `[b]`
-/// Haskell equivalent: `map func items`
-pub fn mapAlloc(
- allocator: std.mem.Allocator,
- func: anytype,
- items: anytype,
-) error{OutOfMemory}!blk:{
- const funcInfo = typeVerify(@TypeOf(func), .{ .@"fn" });
- const itemsInfo = typeVerify(@TypeOf(items), .{ .array, .pointer });
- switch (itemsInfo) {
- .pointer => |p| if(p.size != .many and p.size != .slice)
- @compileError("Expected pointer of size 'many' or 'slice', found " ++ @tagName(p)),
- else =>{},
- }
-
- break :blk []funcInfo.@"fn".return_type.?;
-} {
- const funcInfo = typeVerify(@TypeOf(func), .{ .@"fn" });
- var result = try allocator.alloc(funcInfo.@"fn".return_type.?, items.len);
- for(items, 0..) |item, i|
- result[i] = func(item);
- return result;
-}
-
-/// ```zig
-/// (fn (Allocator, fn (fn (a) b, []a, *[]b) void)
-/// ```
-/// Map a function onto a list of values, using a buffer
-/// Type signature: `(a -> b) -> [a] -> [b]`
-/// `func` is of type `a -> b`, where `items` is of type `[a]` and `buffer` is a pointer to a value of type `[b]`.
-/// Haskell equivalent: `map func items`
-pub fn map(
- func: anytype,
- items: anytype,
- buffer: anytype,
-) void {
- _=typeVerify(@TypeOf(func), .{ .@"fn" });
- const itemsInfo = typeVerify(@TypeOf(items), .{ .pointer, .array });
- const bufferInfo = typeVerify(@TypeOf(buffer), .{ .pointer });
- const bufferChildInfo = typeVerify(bufferInfo.pointer.child, .{ .pointer, .array });
- switch (itemsInfo) {
- .pointer => |p| if(p.size != .many and p.size != .slice)
- @compileError("Expected pointer of size 'many' or 'slice', found '" ++ @tagName(p.size) ++ "'"),
- else =>{},
- }
- switch (bufferChildInfo) {
- .pointer => |p| if(p.size != .many and p.size != .slice)
- @compileError("Expected pointer of size 'many' or 'slice', found '" ++ @tagName(p.size) ++ "'"),
- else =>{},
- }
- for (items, 0..) |item, i|
- buffer.*[i] = func(item);
-}
-
-pub fn curry(func: anytype) blk: {
- const typeInfo = typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn";
- if (typeInfo.params.len == 1)
- break :blk @TypeOf(func);
- if (typeInfo.params.len == 2)
- break :blk fn(typeInfo.params[0].type.?)
- fn(typeInfo.params[1].type.?) typeInfo.return_type.?;
- if (typeInfo.params.len == 3)
- break :blk fn(typeInfo.params[0].type.?)
- fn(typeInfo.params[1].type.?)
- fn(typeInfo.params[2].type.?) typeInfo.return_type.?;
-
-} {
- const typeInfo = typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn";
- if (typeInfo.params.len == 1)
- return func;
- if (typeInfo.params.len == 2)
- return struct {
- fn funct(arg1: typeInfo.params[0].type.?) fn(typeInfo.params[1].type.?) typeInfo.return_type.? {
- return struct {
- fn func2(arg2: typeInfo.params[1].type.?) typeInfo.return_type.? {
- return func(arg1, arg2);
- }
- }.func2;
- }
- }.funct;
- if (typeInfo.params.len == 3)
- return struct {
- fn func1(arg1: typeInfo.params[0].type.?) fn(typeInfo.params[1].type.?) fn(typeInfo.params[2].type.?)
- typeInfo.return_type.? {
- return struct {
- fn func2(arg2: typeInfo.params[1].type.?) fn(typeInfo.params[2].type.?) typeInfo.return_type.? {
- return struct {
- fn func3(arg3: typeInfo.params[2].type.?) typeInfo.return_type.? {
- return func(arg1, arg2, arg3);
- }
- }.func3;
- }
- }.func2;
- }
- }.func1;
-}
-
-pub fn curryHelper(func: anytype, args: anytype) blk: {
- const typeInfo = typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn";
- _=typeVerify(@TypeOf(args), .{ .@"struct" });
- if (typeInfo.params.len == 1)
- break :blk @TypeOf(func);
- const newInfo = std.builtin.Type{
- .@"fn" = .{
- .calling_convention = typeInfo.calling_convention,
- .is_generic = typeInfo.is_generic,
- .params = typeInfo.params[1..],
- .is_var_args = typeInfo.is_var_args,
- .return_type = typeInfo.return_type,
- }
- };
- _=newInfo;
- // break :blk fn(typeInfo.params[args.len].type.?) @Type(newInfo);
- break :blk type;
-} {
- const typeInfo = typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn";
- const argInfo = typeVerify(@TypeOf(args), .{ .@"struct" }).@"struct";
- if (args.len == typeInfo.params.len) return struct {
- pub fn funcCurry() typeInfo.return_type.? {
- return @call(.auto, func, args);
- }
- };
- const newInfo = std.builtin.Type{
- .@"fn" = .{
- .calling_convention = typeInfo.calling_convention,
- .is_generic = typeInfo.is_generic,
- .params = typeInfo.params[1..],
- .is_var_args = typeInfo.is_var_args,
- .return_type = typeInfo.return_type,
- }
- };
- _=newInfo;
- // const newType = @Type(newInfo);
- return struct {
- pub fn funcCurry(arg: typeInfo.params[0].type.?) type {
- var fields: [64]std.builtin.Type.StructField = .{std.builtin.Type.StructField{.name="10",.type=type,.is_comptime=false,.alignment=8,.default_value_ptr=null}} ** 64;
- for (argInfo.fields, 0..) |f, i| {
- fields[i] = f;
- }
- var buf2: [3:0]u8 = undefined;
- fields[args.len] = .{
- .name = blk: {
- break :blk try intToStringZ(args.len, &buf2);
- },
- .type = typeInfo.params[argInfo.fields.len].type.?,
- .is_comptime = false,
- .alignment = @alignOf(typeInfo.params[0].type.?),
- .default_value_ptr = null,
- };
- const newStruct = std.builtin.Type{
- .@"struct" = .{
- .backing_integer = argInfo.backing_integer,
- .decls = argInfo.decls,
- .fields = fields[0..args.len+1],
- .is_tuple = argInfo.is_tuple,
- .layout = argInfo.layout,
- }
- };
-
- // std.debug.print("{any}", .{fields[0..3]});
- const t = @Type(newStruct);
- var newArgs: t = undefined;
- for (@typeInfo(t).@"struct".fields, 0..) |f, i| {
- if (i == args.len) {
- @field(newArgs, f.name) = arg;
- } else @field(newArgs, f.name) = args[i];
-
- }
- return curryHelper(func, newArgs);
- }
- };
-}
-
-fn intToStringZ(int: u32, buf: []u8) ![:0]u8 {
- return try std.fmt.bufPrintZ(buf, "{}", .{int});
-}
-
-// TODO: Add
diff --git a/src/root.zig b/src/root.zig
index 721b2a0..20c6a20 100644
--- a/src/root.zig
+++ b/src/root.zig
@@ -2,4 +2,8 @@ pub const map = @import("map.zig").map;
pub const mapAlloc = @import("map.zig").mapAlloc;
pub const curry = @import("curry.zig").curry;
pub const compose = @import("compose.zig").compose;
+pub const foldl = @import("fold.zig").foldl;
+pub const foldr = @import("fold.zig").foldr;
+pub const foldl1 = @import("fold.zig").foldl1;
+pub const foldr1 = @import("fold.zig").foldr1;
pub const combinators = @import("combinators.zig");