Benutzer:MovGP0/.NET/Lambda Calculus

aus Wikipedia, der freien Enzyklopädie
   MovGP0        Über mich        Hilfen        Artikel        Weblinks        Literatur        Zitate        Notizen        Programmierung        MSCert        Physik      

Lambda Calculus

Notation
Math C#
λx.(λy.(λz.f)) x => (y => (z => f(x, y, z)))
λx.λy.λz.f x => y => z => f(x, y, z)
λxyz.f (x, y, z) => f(x, y, z)

Konversion

α-Konversion
Variablennamen ändern
internal static Func<T, T> Variable<T>(Func<T, Func<Func<T, T>, T>> g, Func<T, T> h) => x => g(x)(y => h(y));

internal static Func<T, T> Variable<T>(Func<T, Func<Func<T, T>, T>> g, Func<T, T> h) => x => g(x)(z => h(z));
β-Reduktion
Variable wird durch Wert ersetzt:
internal static Func<int, int> increment => x => x+1;
// increment(n) wird zu n+1
η-Konversion
Funktionen liefern bei den gleichen Argumenten immer die gleichen Ergebnisse zurück.
Zwei Funktionen sind gleich, wenn sie bei den gleichen Argumenten die gleichen Ergebnisse liefern.

Basics

Komposition
(f1∘f2)(x) = f2(f1(x))
public static partial class FuncExtensions
{
    public static Func<T, TResult2> Ring<T, TResult1, TResult2>(
        this Func<TResult1, TResult2> function2, Func<T, TResult1> function1) =>
            value => function2(function1(value));
}
Assoziativität
(f3∘f2)∘f1 = f3∘(f2∘f1) = f3(f2(f1(x)))
Unit (Identität)
I := λx.x
f∘I = f
I∘f = f
public delegate T Unit<T>(T value);

public static partial class Functions<T>
{
    public static readonly Unit<T> I = x => x;
}
Church Boolean
„True“ (t) liefert ersten Parameter (a);
True := λab.t = λa.λb.t
„False“ (f) liefert zweiten Parameter (b)
False := λab.f = λa.λb.f
let True t f = t
let False t f = f
public delegate Func<dynamic, dynamic> Boolean(object @true);

public static partial class ChurchBoolean
{
    public static readonly Boolean True = @true => @false => @true;

    public static readonly Boolean False = @true => @false => @false;
Logisch-Und
And := λa.λb.a b False = λa.λb.a b (λt.λf.f)
public static partial class ChurchBoolean
{
    public static readonly Func<Boolean, Func<Boolean, Boolean>> And = a => b => (Boolean)a(b)(False);
    // substituting False function
public static Func<Boolean, Func<Boolean, Boolean>>
    And = a => b => a(b)(new Boolean(@true => @false => @false));
}

public static partial class BooleanExtensions
{
    public static Boolean And(this Boolean a, Boolean b) => ChurchBoolean.And(a)(b);
}
Logisch-Oder
Or := λa.λb.a True b
public static Func<Boolean, Func<Boolean, Boolean>> Or = a => b => a(True)(b);

public static Boolean Or(this Boolean a, Boolean b) => ChurchBoolean.Or(a)(b);
Logisch-Nicht
Not := λa.a False True
public static Func<Boolean, Boolean> Not = boolean => boolean(False)(True);

public static Boolean Not(this Boolean a) => ChurchBoolean.Not(a);
Exklusiv-Oder
Xor := λa.λb.a (Not b) b
public static Func<Boolean, Func<Boolean, Boolean>>
    Xor = a => b => a(Not(b))(b);

public static Boolean Xor(this Boolean a, Boolean b) => ChurchBoolean.Xor(a)(b);
System.Boolean
public static partial class ChurchEncoding
{
    // System.Boolean structure to Boolean function.
    public static Boolean Church(this bool boolean) => boolean ? True : False;

    // Boolean function to System.Boolean structure.
    public static bool Unchurch(this Boolean boolean) => boolean(true)(false);
}
If
If := λb.λt.λf.b t f
Eager: C# wertet rechte Austrücke zuerst aus („Applikative Reihenfolge“ statt „Normale Reihenfolge“); dH. then- und else-Branch wird ausgeführt und contition bestimmt anschließend den Rückgabewert.
public static readonly Func<Boolean, Func<dynamic, Func<dynamic, dynamic>>> EagerIf = condition => then => @else => condition  (then) (@else);
Lazy: Factories werden ausgeführt und anschließend der Rückgabewert mittels der Identitätsfunktion bestimmt.
public static readonly Func<Boolean, Func<Func<Unit<dynamic>, dynamic>, Func<Func<Unit<dynamic>, dynamic>, dynamic>>> If = condition => thenFactory => elseFactory => condition (thenFactory) (elseFactory)(Functions<dynamic>.Id);

Quellen

Lambda Calculus via C#