Does the yin yang continuations puzzle make sense in a typed language?

前端 未结 3 1880
别跟我提以往
别跟我提以往 2020-12-29 20:51

This question is related to \"How the yin-yang puzzle works?\". The yin yang example of continuations in scheme looks like this, according to Wikipedia article:



        
3条回答
  •  南方客
    南方客 (楼主)
    2020-12-29 21:50

    It is possible to declare a recursive functional type in C#, a statically-typed language:

    delegate Continuation Continuation(Continuation continuation);
    

    This definition is equivalent to ML’s α : α → α.

    Now we can “translate” the yin-yang puzzle into C#. This does require a transformation for the call/cc, and we need to do the transformation twice because there are two of them in it, but the result still looks very much like the original and still has a yin(yang) call in it:

    Continuation c1 = cc1 =>
    {
        Continuation yin = new Continuation(arg => { Console.Write("@"); return arg; })(cc1);
        Continuation c2 = cc2 =>
        {
            Continuation yang = new Continuation(arg => { Console.Write("*"); return arg; })(cc2);
            return yin(yang);
        };
        return c2(c2);
    };
    c1(c1);
    

    Clearly now, the variable yang is only in local scope, so we can actually optimise it away:

    Continuation c1 = cc1 =>
    {
        Continuation yin = new Continuation(arg => { Console.Write("@"); return arg; })(cc1);
        Continuation c2 = cc2 => yin(new Continuation(arg => { Console.Write("*"); return arg; })(cc2));
        return c2(c2);
    };
    c1(c1);
    

    Now, we realise that those little inline functions really just output a character and otherwise do nothing, so we can unwrap them:

    Continuation c1 = cc1 =>
    {
        Console.Write("@");
        Continuation yin = cc1;
        Continuation c2 = cc2 =>
        {
            Console.Write("*");
            return yin(cc2);
        };
        return c2(c2);
    };
    c1(c1);
    

    Finally, it becomes clear that the variable yin is redundant too (we can just use cc1). To preserve the original spirit though, rename cc1 to yin and cc2 to yang and we get our beloved yin(yang) back:

    Continuation c1 = yin =>
    {
        Console.Write("@");
        Continuation c2 = yang =>
        {
            Console.Write("*");
            return yin(yang);
        };
        return c2(c2);
    };
    c1(c1);
    

    All of the above are the same program, semantically. I think the end-result is a fantastic C# puzzle in itself. So I would answer your question by saying: yes, clearly it makes a lot of sense even in a statically-typed language :)

提交回复
热议问题