I'm playing around with functional programming in D, and have run into a problem with the following code:

--- list.d
import std.variant: Algebraic, This, visit;
import std.typecons: Tuple, tuple;

struct Nil {}
alias List(T) = Algebraic!(
    Nil,
    Tuple!(T, "head", This*, "tail")
);
alias Cons(T) = Tuple!(T, "head", List!T*, "tail");

List!T* list(T)(T[] items...)
{
    if (items.length == 0)
        return new List!T(Nil());
    else
        return new List!T(Cons!T(items[0], list(items[1..$])));
}

string list2string(T)(List!T list)
{
    import std.stdio: write;

    list.visit!(
        (Nil _) => "nil",
(Cons!T cons) => "cons(" ~ cons.head ~ ", " ~ list2string(*cons.tail) ~ ")"
    );
}


unittest {
    List!int* myList = list(1, 2, 3);

assert(list2string(*myList) == "cons(1, cons(2, cons(3, nil)))");
}

---

The error I get is "template list.list2string cannot deduce function from argument types [...]"; i.e., the compiler can't figure out that T is supposed to be 'int'.

My question is, why not? Is there anything I can do to get this to work? The compiler seems to be able to handle this sort of thing in general (e.g., it can deduce 'int' from an argument of type 'Tuple!(int, int)'), so what makes this particular case fail?

Reply via email to