Hello,
I’m new to Zig, and I’m trying to create a Fun
type (code bellow) that captures a function (S => V) or an immediate value (V) after the function has been applied - via Fun.call
.
The code compiles but fails at runtime with the following type mismatch error:
expected type 'fn (u32) root.Fun(u32,u32)', found 'fn (u32) root.Fun(u32,u32)'
The error reports the same type but I’m guessing (with no knowledge of Zig at all) that I’m actually dealing with two different types even if they are rendered exactly the same. (?).
I’ve been trying to search about the (generic function cannot be cast - error) and how to solve it with no success. Any help if greatly appreciated.
[2025-05-15T01:10:18.454Z] Running test: root.zig - basic add functionality
Command failed: zig/linux-x86_64-0.14.0/zig test --test-filter basic add functionality src/root.zig
src/root.zig:34:38: error: expected type 'fn (u32) root.Fun(u32,u32)', found 'fn (u32) root.Fun(u32,u32)'
return .{ ._fun = closure.call };
~~~~~~~^~~~~
src/root.zig:34:38: note: generic function cannot cast into a non-generic function
src/root.zig:13:31: note: called from here
const f = Fun(u32, u32).mk(closure.call);
~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
const std = @import("std");
const testing = std.testing;
test "basic add functionality" {
const closure = struct {
fn call(a: u32) u32 {
return a + 1;
}
};
const f = Fun(u32, u32).mk(closure.call);
const g = f.call(22);
try testing.expect(g.value() == 23);
}
fn Fun(comptime S: type, comptime V: type) type {
return union(enum) {
fn call(self: Self, s: S) Self {
return self._fun(s);
}
fn value(self: Self) V {
return self._imm;
}
fn mk(fun: fn (S) V) Self {
const closure = struct {
fn call(s: S) Self {
return .{ ._imm = fun(s) };
}
};
return .{ ._fun = closure.call };
}
const Self = @This();
_imm: V,
_fun: fn (S) Self,
};
}
EDIT: for context, I’m trying to learn Zig by creating an implementation of my Fx.go - Algebraic Effect system for Golang, here’s my current progress – the code above is the minimal failing example I could made. Just wanted to provide some context on why I’m using an union, in my effect library, an Effect (Fx) is a union: either an existing value or a suspended function), but I don’t think that is even part of the issue here.