Accumulating Types in C#

PartI:
------
Goul: I want to couple values together, in a statically strongly typed manner in C# (3.5) which has not an internal support for tuples in it's compiler; without defining new types.

Code:

namespace TypePiling
{
    using System.Text;
    using System;
    using System.IO;

    public static class Ex
    {
        public static Tuple<T, U> Glue<T, U>(this T t, U u)
        {
            return new Tuple<T, U> { First = t, Second = u };
        }
    }

    public class Tuple<T, U>
    {
        public T First { get; set; }
        public U Second { get; set; }

        public override string ToString()
        {
            var result = new StringBuilder();

            if (this.First != null) result.Append(string.Format("{0}", this.First.ToString()));
            if (this.Second != null) result.Append(string.Format(", {0}", this.Second.ToString()));

            return string.Format("{{ {0} }}", result.ToString().TrimStart(',').Trim());
        }
    }

    public static class Test
    {
        public static void Test1()
        {
            var i = 10;
            var g0 = i.Glue("Hi");
            var g1 = g0.Glue((byte)0xFF);
            var g2 = g1.Glue(100.0);
            var g3 = g2.Glue('A');
            var g4 = g3.Glue((float)1000);

            using (var sw = new StreamWriter("output.txt"))
            {
                sw.WriteLine(g0);
                sw.WriteLine(g1);
                sw.WriteLine(g2);
                sw.WriteLine(g3);
                sw.WriteLine(g4);

                sw.Flush();
            }

            System.Diagnostics.Process.Start("output.txt");
        }
    }
}

This code does what I want and g4 will be:
{ { { { { 10, Hi }, 255 }, 100 }, A }, 1000 }

This is my first problem; as you see I do that by put previous value and next value in a new container. So previous values are pile down in First. I want them be piled up in Second, so g4 should be:
{ 10, { Hi, { 255, { 100, { A, 1000 } } } } }

I it possible in C# 3.5? If not why?

Part II:
--------
In trying to answer Part I; I have wrote another Extension Method in class Ex:

public static Tuple<T, Tuple<U, V>> Glue<T, U, V>(this Tuple<T, U> t, V v)
{
    return new Tuple<T, Tuple<U, V>> { First = t.First, Second = t.Second.Glue(v) };
}

This should do it in a recursive manner. Let see what is the out put:
{ 10, Hi }
{ 10, { Hi, 255 } }
{ 10, { { Hi, 255 }, 100 } }
{ 10, { { { Hi, 255 }, 100 }, A } }
{ 10, { { { { Hi, 255 }, 100 }, A }, 1000 } }

What? What happened at step 3? Sure the compiler recognized { Hi, 255 } as Tuple<string, byte>; but why the first version of Glue executed not the second one, overloaded for a Tuple<T, U>?

Is this something about generics in C#?

After all implementing tuples in a statically strongly typed manner without compiler support (internal or by a macro system) is pointless, I know. But from this pointless try I have touched another problem: In C# I can not have real accumulated types, but just parametrized types which does not provide enough tools for composition.

Thanks in advance

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Just make Glue a method on

Just make Glue a method on Tuple instead of an extension method:

public Tuple<T, Tuple<U, V>> Glue<V>(V v)
{
  return new Tuple<T, Tuple<U, V>> { First = this.First, Second = new Tuple<U,V> { First = this.Second, Second = v } };
}

I used these sorts of "accumulating types" in a few cases, for instance an embedded stack language in C#.

Does not work

That does not do it. If we run the code, output would be (by removing the static from the declaration of method and adding it to Tuple class itself):

{ 10, Hi }
{ 10, { Hi, 255 } }
{ 10, { { Hi, 255 }, 100 } }
{ 10, { { { Hi, 255 }, 100 }, A } }
{ 10, { { { { Hi, 255 }, 100 }, A }, 1000 } }

As we can see, again at step 3, a Tuple<string, byte> is placed in First.

You're right, because the

You're right, because the inner tuple is inaccessible to Glue, essentially forcing left nesting. I'm not sure what the big deal is anyway, as any algorithm defined using left nesting is invertible to right nesting, and vice versa.

Your Tuple, like the Stack type from my post, basically must use type argument T as a row variable for record extension. As for tuples themselves, .NET can certainly support them.

If you simply prefer the other nesting level, then you must treat Glue as a "push" operation on a stack, instead of an "append" to a record:

public static Tuple<U, T> Glue<T, U>(this T t, U u)
{
  return new Tuple<U, T> { First = u, Second = t };
}

That constructs the record with the correct nesting, but in reverse order.

Just Coding

Just coding; no big deal. I was looking if there is a way to do some kind of structural deconstructing - and constructing - in C#. My other problem is why the overloaded method for a Tuple<T, U> is not called at step 3?

Static call, not dynamic dispatch

The call "t.Second.Glue(v)" is a static call to whatever function matches the compile-time knowledge of t.Second and v, not a dynamic dispatch. That's why it resolves to the function that it does, because it does not know whether U is a tuple or a primitive type, and so it calls the most general function matching the signature, public static Tuple<T, U> Glue<T, U>(this T t, U u).

In any case, the only way to generate your desired nesting is to completely unwrap the tuple, and generate a whole new sequence of tuples. It's just too inefficient in practice.

Stack

You are right. I thought it might call the other method at runtime, based on type of it's argument (oops!).

In case of your stack based language this approach fits in, since MSIL is a stack-based language itself.

In fact this code, seems to be a statically typed stack! Of course ugly enough in C# to not be pragmatic, since C# does type inference just in the scope of a method body.

In fact this code, seems to

In fact this code, seems to be a statically typed stack! Of course ugly enough in C# to not be pragmatic, since C# does type inference just in the scope of a method body.

Yes, it statically types the stack effects as you assemble an MSIL program. Theoretically, any assembled program that type checks will run without errors.

I'm not sure it's entirely useless in C#, since any staged function you care to write in C# will have a stack effect which either simply consumes elements relative to the row variable, or adds elements relative to the row variable; this incremental effect should make it usable enough for small tasks at least, though I haven't played much with it beyond the prototype.

Wrong Target

My apology in advance. Third sentence was about my code - which contains the "ugly" word - and in fact I meant that this thing that I named Tuple is a statically typed stack.

Your approach to using MSIL is not useless (IMO) and I have thought of implementing some "macro"s (...lispy ;) ) based on it and with Expression Trees in C# 4.0 (which seems to cover even syntax for constructing runtime types) there will be even more rooms for investigation of new aspects of your in-C# MSIL.

It seems that C# 4.0 will provide full support for tuples; yet I do not know if we have to still have ugly part of C# syntax (Tuple) in front of us in the editor.

&lt; and &gt;

I have messed up with posting my code because of < and > in generic C# statements. It is fixed by replacing them with &lt; and &gt;