Функциональный язык для нетипизированного лямбда-исчисления - PullRequest
5 голосов
/ 25 октября 2011

Есть ли интерпретатор (или компилятор) для нетипизированного лямбда-исчисления? (Согласно этой теме это возможно.) Я признаю, что он будет мало полезен в качестве языка программирования, особенно если большая часть языка (например, цифры и логические операторы) была реализована (либо пользователем). или библиотекой) на самом языке. Тем не менее, я все еще думаю, что это будет забавный инструмент, полезный для изучения и изучения исчисления. Для этого интерпретатор предпочтительнее компилятора, хотя бы любой из них будет работать. Кто-нибудь знает о такой программе?

Ответы [ 7 ]

7 голосов
/ 14 ноября 2012

Вы можете использовать любой нетипизированный язык с лямбда-абстракциями. Например, Python или JavaScript. Есть два основных недостатка:

  1. Эти языки не имеют ленивой оценки. Это означает, что не все лямбда-члены будут сходиться, даже если они имеют нормальную форму. Вы должны принять это во внимание и соответственно изменить задачу.
  2. Вы не увидите результат в виде лямбда-термина в нормальной форме. Вы должны знать, чего ожидать от результата, и использовать язык для его оценки, чтобы можно было что-то отобразить.

Зная это, давайте сделаем пример на Python: Сначала мы создаем вспомогательные функции для преобразования между числами и церковными цифрами:

# Construct Church numeral from an integer
def int2church(n):
    def repeat(f, m, x):
        if (m == 0): return x
        else: return f(repeat(f, m-1, x))
    return lambda f: (lambda x: repeat(f, n, x))

def church2int(l):
    return l(lambda x: x + 1)(0)

теперь мы можем определить стандартные операции над числами:

zero = int2church(0)
one = int2church(1)

pred = lambda n: lambda f: lambda x: n(lambda g: lambda h: h(g(f)))(lambda u: x)(lambda u: u)

mul = lambda m: lambda n: (lambda f: m(n(f)))

expn = lambda n: lambda m: m(n)

tetra = lambda n: lambda m: m(expn(n))(one)

и вычислите, например, 4 3 :

expn = lambda n: (lambda m: m(n))

a = int2church(4)
b = int2church(3)
print church2int(expn(a)(b))

или тетрация :

a = int2church(5)
b = int2church(2)
print church2int(tetra(a)(b))

Чтобы выразить еще более интересные вещи, мы можем определить Y комбинатор:

y = lambda f: (lambda x: f(lambda v: x(x)(v))) (lambda x: f(lambda v: x(x)(v)))

и вычислить, например, факториалы:

true = lambda x: (lambda y: x)
false = lambda x: (lambda y: y)

iszero = lambda n: n(lambda x: false)(true)

fact = y(lambda r: lambda n: iszero(n)(one)(mul(n)(lambda x: r(pred(n))(x))))
print church2int(fact(int2church(6)))

Обратите внимание, что комбинатор Y пришлось адаптировать для строгой оценки, используя η-расширение , а также функцию факториала, чтобы избежать бесконечной рекурсии из-за строгой оценки.

6 голосов
/ 25 октября 2011

Бенджамин Пирс предоставляет реализации нетипизированного и простого типа λ-исчисления, которые сопровождают его учебник Типы и языки программирования .Они написаны на OCaml и содержат примеры определений.Однако не должно быть трудностей написать интерпретатор или компилятор для простых λ-исчислений.

3 голосов
/ 25 октября 2011

Я ассистент по курсу функционального программирования.Для педагогической цели мы увидели этот онлайн лямбда-исчисление редуктор как забавный и полезный инструмент для изучения исчисления.У них также есть доступный исходный код на SML, если вы хотите поиграть с ним.

3 голосов
/ 25 октября 2011

Используя несколько трюков, это можно сделать практически на любых функциональных языках. По крайней мере, я видел что-то подобное в Haskell и OCaml. Однако иногда приходится обходить ограничения систем типов. Обычно вы получаете «нетипизированную» функцию, реализуя ее как единую систему. Таким образом, каждая лямбда-функция будет иметь тип

type lambda = lambda -> lambda

В настройках по умолчанию, например, OCaml не разрешит такой рекурсивный тип, но это можно обойти, например, определив:

type lambda = L of lambda -> lambda
2 голосов
/ 03 ноября 2011

Я написал один ранее в этом году. Вот оно .

1 голос
/ 25 марта 2013

Я создал веб-переводчик для языка, основанного на лямбда-исчислении, который я называю pureƒn , чтобы изучить работу лямбда-исчисления. Это может быть полезно для людей, желающих изучать и испытывать некоторые из фундаментальных принципов информатики в интерактивном режиме с минимальной сложностью записи.

pureƒn - это среда программирования, основанная на функциональности лямбда-исчисления, но с упрощенной системой обозначений. pureƒn позволяет определять, применять и сокращать функциональные абстракции. Обозначения и синтаксис минимальны, но достаточны для того, чтобы легко понять базовые понятия.

Базовый компилятор был написан на Python и компилирует абстракции в функции, которые автоматически приводятся к нормальной форме (если это возможно) при применении друг к другу. Это означает, что если вы определяете функции комбинатора S, K и I, а затем применяете их как SKK, возвращаемая функция будет функцией I, а не просто функцией, которая ведет себя как I, то есть будет выполняться следующее:

>>>S(K)(K) is I
True
0 голосов
/ 03 ноября 2011

Здесь написано на Python. Это кажется очень незрелым, но это интересное начало реализации одного Python. Это зависит от модуля ply.

Здесь еще один (вроде) для C ++ - очень интересно.

Если ваше основное намерение состоит в том, чтобы включить некоторую базовую автоматизацию в изучение лямбда-исчисления (например, пытаться получить арифметические операции для себя) и конкретных церковных чисел и логических значений, примитивное, но простое в реализации решение заключается в ограничении себя к небольшому подмножеству Python, в котором вы можете определить свои собственные церковные цифры и операторы и проверить их с помощью функций, которые преобразуют их в обычные типы Python. Функция для этого для церковных цифр:

lambda churchnum: churchnum(lambda x: x+1)(0)

И один для церковных логических выражений:

lambda churchbool: churchbool(True)(False)
...