Lambda Calculus via C # (16) Codage de la liste des églises avec 2 paires d'églises en tant que nœud

Lambda Calculus via C # (16) Codage de la liste des églises avec 2 paires d'églises en tant que nœud

[LINQ via la série C#]

[Calcul Lambda via la série C#]

Dernière version :https://weblogs.asp.net/dixin/lambda-calculus-via-csharp-5-list

Liste d'église codée par la partie précédente avec une paire d'église (2-tuple) comme nœud de liste. Une autre méthode consiste à utiliser 2 tuples comme nœud, l'un enveloppant l'autre.

  • Item1 du tuple externe sera le drapeau nul (une valeur booléenne Church pour indiquer que ce nœud est nul ou non)
  • Item2 du tuple externe est le tuple interne :
    • Item1 du tuple interne est la valeur de ce nœud
    • Item2 du tuple intérieur est le nœud suivant

EstNull et Null

La définition ci-dessus peut avoir immédiatement :

IsNull2 = λl.(Item1 l)

Donc Null est facile à définir pour :

Null2 = λf.True

renvoie juste True quoi qu'il arrive, ce qui garantit également que IsNull ci-dessus fonctionne.

C# :

// ListNode2 is the alias of Tuple<Boolean, Tuple<T, ListNode2<T>>>
public delegate object ListNode2<out T>(Boolean<Boolean, Tuple<T, ListNode2<T>>> f);

public static partial class ChurchList2
{
    // Null = f => ChurchBoolean.True
    public static object Null<T>
        (Boolean<Boolean, Tuple<T, ListNode2<T>>> f) => new Boolean(ChurchBoolean.True);

    // IsNull = node => node.Item1()
    public static Boolean IsNull<T>
        (this ListNode2<T> node) => new Tuple<Boolean, Tuple<T, ListNode2<T>>>(node).Item1();
}

Créer, Valoriser et Suivant

Encore une fois des définitions ci-dessus :

CreateListNode2 = λv.λn.CreateTuple False (CreateTuple v n)
Value2 = λl.Item1 (Item2 l)
Next2 = λl.If (IsNull2 l) (λx.l) (λx.(Item2 (Item2 l)))

Next utilise à nouveau If pour renvoyer Null comme nœud suivant, identique à la liste Church précédente implémentée par 1 paire Church pour chaque nœud.

C# :

public static partial class ChurchList2
{
    // Create = value => next => ChurchTuple.Create(ChurchBoolean.False)(ChurchTuple.Create(value)(next))
    public static Func<ListNode2<T>, ListNode2<T>> Create<T>
        (T value) => next =>
            new ListNode2<T>(ChurchTuple.Create<Boolean, Tuple<T, ListNode2<T>>>
                (ChurchBoolean.False)
                (ChurchTuple.Create<T, ListNode2<T>>(value)(next)));

    // Value = node => node.Item2().Item1()
    public static T Value<T>
        (this ListNode2<T> node) => new Tuple<Boolean, Tuple<T, ListNode2<T>>>(node).Item2().Item1();

    // Next = node => ChurchBoolean.If(node.IsNull())(_ => node)(_ => node.Item2().Item2())
    public static ListNode2<T> Next<T>
        (this ListNode2<T> node) =>
            ChurchBoolean.If<ListNode2<T>>(node.IsNull())
                (_ => node)
                (_ => new Tuple<Boolean, Tuple<T, ListNode2<T>>>(node).Item2().Item2());
}

Index

Identique à la partie précédente :

Index2 = λl.λi.i Next2 l

C# :

public static partial class ChurchList2
{
    // Index = start => index = index(Next)(start)
    public static ListNode2<T> Index<T>
        (this ListNode2<T> start, _Numeral index) => index.Numeral<ListNode2<T>>()(Next)(start);
}

Tests unitaires

Encore une fois, la même chose que la partie précédente :

[TestClass()]
public class ChurchList2Tests
{
    [TestMethod()]
    public void CreateValueNextTest()
    {
        ListNode2<int> node1 = ChurchList2.Create(1)(ChurchList2.Null);
        ListNode2<int> node2 = ChurchList2.Create(2)(node1);
        ListNode2<int> node3 = ChurchList2.Create(3)(node2);
        Assert.AreEqual(1, node1.Value());
        Assert.AreEqual(ChurchList2.Null, node1.Next());
        Assert.AreEqual(2, node2.Value());
        Assert.AreEqual(node1, node2.Next());
        Assert.AreEqual(3, node3.Value());
        Assert.AreEqual(node2, node3.Next());
        Assert.IsTrue(new ListNode2<object>(ChurchList2.Null).Next().IsNull()._Unchurch());
    }

    [TestMethod()]
    public void NullIsNullTest()
    {
        ListNode2<int> node = ChurchList2.Create(1)(ChurchList2.Null);
        Assert.IsTrue(ChurchList2.IsNull<object>(ChurchList2.Null)._Unchurch());
        Assert.IsFalse(node.IsNull()._Unchurch());
    }

    [TestMethod()]
    public void IndexTest()
    {
        ListNode2<int> node1 = ChurchList2.Create(1)(ChurchList2.Null);
        ListNode2<int> node2 = ChurchList2.Create(2)(node1);
        ListNode2<int> node3 = ChurchList2.Create(3)(node2);
        Assert.AreEqual(node3, node3.Index(0U._Church()));
        Assert.AreEqual(node2, node3.Index(1U._Church()));
        Assert.AreEqual(node1, node3.Index(2U._Church()));
        Assert.IsTrue(node3.Index(3U._Church()).IsNull()._Unchurch());
        Assert.IsTrue(node3.Index(4U._Church()).IsNull()._Unchurch());
        Assert.IsTrue(node3.Index(5U._Church()).IsNull()._Unchurch());
    }
}