Лямбда-исчисление

Рассмотрение неклассического лямбда-исчисления, основное назначение. Особенности системы вывода результатов. Характеристика программирования на языке Haskell. Знакомство со способами преобразования выражений в лямбда-исчислении. Анализ функций CONS.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 05.04.2013
Размер файла 79,7 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

ZERO = лf.лx.x -- функция f ноль раз применяется к аргументу x, так что аргумент возвращается неизменным

(N+1) = лf.лx.f (N f x)

Заметим, кстати, что константа ZERO определена в точности так же, как константа FALSE, однако далеко идущих выводов из этого сходства делать все же не следует. Из приведенного определения целых чисел немедленно следует определение функции следования, которая добавляет единицу к своему аргументу:

SUCC = лn.лf.лx.f (n f x)

Теперь нетрудно также определить операции сложения и умножения целых чисел. Так, например, можно сказать, что для того, чтобы сложить два числа m и n, надо m раз увеличить число n на единицу. Аналогично, чтобы умножить m на n, надо m раз применить функцию увеличения на n к нулю. Отсюда следуют определения:

PLUS = лm.лn.m SUCC n

MULT = лm.лn.m (PLUS n) ZERO

К сожалению, определить операции вычитания в представленной нами арифметике совсем не так просто. Прежде всего определим функцию PRED, которая выдает предыдущее натуральное число для всех чисел, больших нуля, а для аргумента, равного нулю, выдает также ноль. Одно из возможных определений такой функций выглядит следующим образом:

PRED = лn.лf.лx.n (лg.лh.h (g f)) (лu.x) (лu.u)

Проверьте, что применение этой функции к значению ZERO действительно выдает в качестве результата ZERO, а применение этой функции к, скажем, значению 2 (представленному функцией лf.лx.f (f x)) может быть преобразовано к значению 1 (функции лf.лx.f x). Такое упражнение позволит вам понять, как происходит уменьшение количества применений функции f к аргументу. Теперь уже нетрудно определить и функцию вычитания на множестве натуральных чисел, которая для заданных аргументов m и n выдает значение (m-n) при m ? n и выдает ноль при m < n.

MINUS = лm.лn.n PRED m

Арифметику целых чисел можно теперь связать с логическими значениями, определив функции сравнения чисел. Проще всего определить функцию сравнению числа с нулем. Вот одно из возможных определений для такой функции.

EQ0 = лn.n (лx.FALSE) TRUE

Очевидно, что если применить функцию к значению ZERO, то функция (лx.FALSE) не будет применена ни разу к своему аргументу, поэтому результатом применения функции будет значение TRUE. Если же значение аргумента отлично от нуля, то функция (лx.FALSE) после первого же применения выдаст значение FALSE, и в дальнейшем, сколько бы раз ее ни применять, выдаваемым значением так и будет оставаться FALSE. Теперь можно определить функции сравнения двух чисел с помощью операций GE ("больше или равно") и LE ("меньше или равно"), используя только что определенную операцию сравнения с нулем и операцию вычитания натуральных чисел MINUS.

GE = лm.лn.EQ0 (MINUS m n)

LE = лm.лn.EQ0 (MINUS n m)

Остальные операции сравнения легко выражаются через эти операции сравнения и уже определенные ранее логические операции:

GT = лm.лn.NOT (LE m n)

LT = лm.лn.NOT (GE m n)

EQ = лm.лn.AND (GE m n) (LE m n)

NEQ = лm.лn.NOT (EQ m n)

Теперь, когда уже определена арифметика и логика, давайте, вооруженные опытом описания различных стандартных функций построим функции для формирования составных значений, подобных кортежам или спискам. Представляемые нами составные значения будут больше всего напоминать списки, как они определены в языке LISP, то есть списки элементов самого разного типа (элементом такого списка может быть любое значение, в том числе другой список, число, логическое значение или, вообще говоря, любая функция). Для создания таких списков необходимо определить одно базовое значение - пустой список - и функции, позволяющие из двух заданных значений создавать их пару (функция CONS), а также выделять первый и второй элемент пары (функции HEAD и TAIL). Для того, чтобы можно было исследовать списки в программах, требуется определить также по крайней мере одну логическую функцию NULL, которая выдает значение TRUE или FALSE в зависимости от того, является ли ее аргумент пустым списком или нет.

Функция CONS может соединять в пару два своих аргумента, просто создавая функцию, которая будет применять свой аргумент к обеим частям пары как к двум своим аргументам. Другими словами, если H и T - два произвольных значения, то их пару можно представить функцией (лs.s H T). Таким образом, функция CONS получает следующее определение:

CONS = лh.лt.лs.s h t

Для того, чтобы из составного значения (лs.s H T) выделить первый элемент H, надо применить эту функцию к такому значению s, которое выдаст первый из двух своих аргументов. Таким значением является уже определенная нами ранее константа TRUE. Ясно, что результатом применения (лs.s H T) TRUE будет значение H. Таким образом, функция HEAD получает следующее определение:

HEAD = лl.l TRUE

Разумеется, функция будет работать "правильно", только если ее аргументом будет пара, скажем, составленная с помощью функции CONS. Аналогичным образом определяется и функция TAIL.

TAIL = лl.l FALSE

Функция NULL должна выдавать в качестве результата FALSE для любой пары вида (лs.s H T). Поэтому можно определить эту функцию таким образом, чтобы она применяла свой аргумент к функции, выдающей значение FALSE для любых двух аргументов: лh.лt.FALSE. Отсюда следует определение

NULL = лl.l (лh.лt.FALSE)

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

NIL = лx.TRUE

Давайте проверим, что наши определения работают, на простом примере: проверим, что значением выражения NULL (HEAD (CONS NIL A)) будет TRUE, каково бы ни было выражение A. Для этого будем последовательно подставлять в наше выражение определения введенных нами функций и производить редукции выражения по мере возможности. В результате получим следующую последовательность эквивалентных выражений.

NULL (HEAD (CONS NIL A))

(лl.l (лh.лt.FALSE)) (HEAD (CONS NIL A))

(HEAD (CONS NIL A)) (лh.лt.FALSE)

((лl.l TRUE) (CONS NIL A)) (лh.лt.FALSE)

((CONS NIL A) TRUE) (лh.лt.FALSE)

(((лh.лt.лs.s h t) NIL A) TRUE) (лh.лt.FALSE)

((лs.s NIL A) TRUE) (лh.лt.FALSE)

(TRUE NIL A) (лh.лt.FALSE)

NIL (лh.лt.FALSE)

(лx.TRUE) (лh.лt.FALSE)

TRUE

Мы получили ожидаемый результат. Подобным же образом можно представить в чистом лямбда-исчислении любое выражение, в том числе содержащее рекурсивные вызовы (применяя преобразование, использующее Y-комбинатор). Таким образом, можно сказать, что мы получили возможность эквивалентного представления любой функциональной программы, написанной в нашем расширенном лямбда-исчислении, с помощью лишь средств чистого лямбда-исчисления.

На самом деле использовать чистое лямбда-исчисление в практических целях, конечно же, неудобно. Даже для того, чтобы сложить числа 2 и 5, потребуется выполнить огромное количество редукций, а реализация рекурсии в виде применения Y-комбинатора - это тоже далеко не самый простой способ выполнения рекурсивных функций. Поэтому в дальнейшем мы будем использовать только расширенное лямбда-исчисление, содержащее встроенные константы и функции, а также конструкцию let для эффективной реализации механизма ленивых вычислений. Более того, мы еще расширим наше лямбда-исчисление для того, чтобы явно представить в нем рекурсию, что позволит нам обойтись без применения Y-комбинатора. Новая конструкция по виду и по действию будет напоминать конструкцию let, разница будет состоять только в том, что в новой конструкции letrec x = e1 in e2 в выражении e1 допускаются рекурсивные обращения к переменной x. Это, в частности, приводит к тому, что новая конструкция уже не может быть представлена в виде эквивалентного выражения (лx.e2) e1, так как в выражении аргумента могут встречаться обращения к связанной переменной x. Эквивалентное выражение в чистом лямбда-исчислении может быть получено путем применения Y-комбинатора.

Рассмотрим правила редукций, применяемые в условиях существования рекурсивных определений, на примере преобразования выражения

letrec FACT = лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n))) in FACT 2

letrec FACT = лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n))) in (лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n)))) 2

letrec FACT = лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n))) in IF (EQ0 2) 1 (MULT 2 (FACT (PRED 2)))

letrec FACT = лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n))) in MULT 2 (FACT 1)

letrec FACT = лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n))) in MULT 2 ((лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n)))) 1)

letrec FACT = лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n))) in MULT 2 (IF (EQ0 1) 1 (MULT 1 (FACT (PRED 1))))

letrec FACT = лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n))) in MULT 2 (MULT 1 (FACT 0))

letrec FACT = лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n))) in MULT 2 (MULT 1 ((лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n)))) 0))

letrec FACT = лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n))) in MULT 2 (MULT 1 (IF (EQ0 0) 1 (MULT 0 (FACT (PRED 0)))))

letrec FACT = лn.IF (EQ0 n) 1 (MULT n (FACT (PRED n))) in MULT 2 (MULT 1 1)

В этом примере в конструкции letrec x = e1 in e2 выражение e1 уже находится в СЗНФ, поэтому при вычислении выражения e2 происходит просто подстановка значения e1 в выражение e2 вместо x. Однако, поскольку это выражение содержит рекурсивные обращения к определяемой переменной (в данном примере - FACT), то для дальнейшего вычисления требуется сохранить связь переменной со значением e1. Эта связь исчезает только тогда, когда в результате преобразований из выражения e2 исчезает сама переменная x.

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

Размещено на Allbest.ru

...

Подобные документы

  • Ознакомление с лямбда-выражениями и функциями языка Lisp. Этапы разработки алгоритма функции, производящей удаление из исходного списка всех элементов с четными номерами. Код программы, адаптированной для использования в базах данных больниц и ВУЗов.

    лабораторная работа [65,5 K], добавлен 21.05.2014

  • Особенности вывода на экран содержимого файла BAZA.txt. Анализ функций вывода информации о количестве каждой марки машин. Рассмотрение способов проектирования тестов программы методами черного ящика. Проблемы программирования на языке высокого уровня.

    контрольная работа [1,6 M], добавлен 04.01.2015

  • Приемы работы с инструментальной средой программирования С++. Кодирование арифметических и логических выражений с использованием стандартных библиотечных функций ввода, вывода в С++. Описание переменной вещественного типа в языке программирования С++.

    лабораторная работа [137,9 K], добавлен 13.06.2014

  • Общая характеристика программной модели процессора Intel x86. Анализ особенностей регистров общего назначения. Назначение команд безусловной передачи управления, рассмотрение функций. Знакомство с проблемами программирования на языке Ассемблера.

    курсовая работа [1,6 M], добавлен 04.02.2014

  • Понятие и принципы построения трансляторов. Методика написания программы на языке программирования С++, реализующей определенные действия над математическими выражениями. Написание транслятора с языка математических выражений на язык деревьев вывода.

    курсовая работа [423,3 K], добавлен 24.08.2009

  • Команды преобразования выражений, используемые в системе Maple, их назначение и принцип действия, отличия активной и пассивной формы. Команда simplify () для упрощения выражений, случаи ее применения. Разложение полинома на множители: factor ().

    лабораторная работа [57,8 K], добавлен 15.07.2009

  • Особенности построения алгоритма поиска адресов e-mail, ICQ и имен пользователей в файлах, с использованием формата вывода html страницы, а также его реализация с помощью GHCi языка Haskell. История создания и принципы работы с wxWidgets и wxHaskell.

    курсовая работа [687,3 K], добавлен 21.12.2009

  • Положения машины Тьюринга. Алгоритмически неразрешимые проблемы: "остановка", эквивалентность алгоритмов, тотальность. Свойства алгоритма: дискретность, детерминированность, результативность, массовость. Выбор структуры данных. Решение на языке Haskell.

    курсовая работа [957,6 K], добавлен 16.11.2013

  • Особенности реализации алгоритма проверки логического следования методом резолюции. Реализация проекта на логическом языке Prolog и на функциональном языке Haskell: сравнительная характеристика. Знакомство с листингом программы на необходимых языках.

    курсовая работа [57,0 K], добавлен 14.07.2012

  • Особенности способов описания языков программирования. Язык программирования как способ записи программ на ЭВМ в понятной для компьютера форме. Характеристика языка Паскаль, анализ стандартных его функций. Анализ примеров записи арифметических выражений.

    курсовая работа [292,0 K], добавлен 18.03.2013

  • Исследование арифметических выражений и разработка простых программ. Таблица переменных для алгоритма и программы. Алгоритм решения, текст программы на языке С. Разработка программы вычисления значений выражений, сравнение результатов с ручным подсчетом.

    лабораторная работа [282,7 K], добавлен 30.01.2015

  • Язык программирования Турбо Паскаль. Запись алгоритма на языке программирования и отладка программы. Правила записи арифметических выражений. Стандартное расширение имени файла, созданного системным редактором. Составной оператор и вложенные условия.

    курсовая работа [75,0 K], добавлен 21.03.2013

  • Программа на языке Си как набор операторов разделенных между собой точкой с запятой, знакомство с особенностями структуры, назначение. Общая характеристика линейных и циклических вычислительных процессов. Рассмотрение основных видов операторов цикла.

    презентация [139,7 K], добавлен 26.07.2013

  • Рассмотрение основных этапов создания приложения "Записная книжка", основное предназначение. Анализ способов выбора среды программирования. Знакомство с элементом управления Data Grid View. Общая характеристика методов конструкции языка программирования.

    контрольная работа [1002,4 K], добавлен 21.06.2014

  • Сигнал как некоторое средство для передачи информации. Знакомство с параллельными алгоритмами двумерного быстрого преобразования Фурье, анализ способов вычисления. Общая характеристика процессора Power5 64-bit RISC. Рассмотрение функций библиотеки MPI.

    дипломная работа [1,6 M], добавлен 09.10.2013

  • Вычисление выражений, использование стандартных функций; работа с графикой. Порядок действий при вычислении, способы ввода данных с клавиатуры. Построение таблиц функций. Организация циклов в программе, итерационные процессы. Работа с массивами чисел.

    контрольная работа [614,7 K], добавлен 16.09.2012

  • Совместимость и преобразование типов данных. Создание информационно-поисковой системы на языке программирования Паскаль. Описание интерфейса, каждого блока программы "Картотека больных". Рассмотрение результатов работы программы, сортирования данных.

    курсовая работа [368,9 K], добавлен 18.05.2015

  • Рассмотрение правил записи, способов ввода и вывода, использования функций обработки символьных данных в Pascal. Описание алгоритмизации и программирования файловых структур данных, проектирования структуры файла. Ознакомление с работой данных массива.

    курсовая работа [336,2 K], добавлен 27.06.2015

  • Знакомство с наиболее известными технологиями программирования. Особенности разработки программ для вычисления интеграла по формуле средних прямоугольников. Общая характеристика методов структурного программирования. Рассмотрение формулы Симпсона.

    курсовая работа [1,3 M], добавлен 03.03.2015

  • Особенности объектно-ориентированного программирования. Основные возможности языка программирования Java, классификация платформ. Создание программы, обеспечивающей вычисление арифметических выражений. Руководство пользователя и характеристика функций.

    курсовая работа [1,2 M], добавлен 07.07.2012

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.