Модульность - Функциональные языки программирования

Механизм модульности позволяет разделять программы на несколько сравнительно независимых частей (модулей) с четко определенными связями между ними. Тем самым облегчается процесс проектирования и последующей поддержки больших программных систем. Поддержка модульности не является свойством именно функциональных языков программирования. Существуют очень развитые модульные императивные языки. В качестве примеров подобных языков можно привести Modula-2 и Ada-95. В этой статье, однако, речь идет о языках функционального программирования. Поэтому для примера рассмотрим систему модулей функционального языка Standard ML. Standard ML - строго типизированный язык, это накладывает свой отпечаток и на систему модулей. Поэтому каждый модуль (в терминах языка - структура) имеет тип (сигнатуру). Сигнатура определяет часть структуры доступную извне. Именно так в Standard ML реализуется механизм абстракции данных. По аналогии с соответствиями сигнатура = тип и структура = значение, должно быть определено и какое-нибудь соответствие понятию функции. В самом деле, в Standard ML существует возможность определять функции над структурами. Такие функции называются функторами, по аналогии с термином из общей алгебры. Функторы позволяют преобразовывать структуры, соответствующие одной сигнатуре, в структуры, соответствующие другой, тем самым одновременно являя собой механизм реализующий наследование и параметрический полиморфизм на уровне целых модулей. Standard ML является одним из немногих функциональных языков с такой интересной системой модулей. В Haskell, например, реализована намного более простая система, сходная с системой модулей в языке Modula-2.Функции - это значенияв функциональных языках функции могут быть переданы другим функциям в качестве аргумента или возвращены в качестве результата. Функции, принимающие функциональные аргументы, называются функциями высших порядков или функционалами. Самый, пожалуй, известный функционал, это map. map применяет некоторуюфункцию ко всем элементам списка, формируя из результатов другой список. Например, определив функцию возведения целого числа в квадрат как:

Square::Int ->Int

Square n = n * n

Мы можем воспользоваться этой функцией для возведения в квадрат всех элементов списка

L2 = mapsquare [1, 2, 3, 4] -- Результат - Список [1, 4, 9, 16]

Каждый тип имеет литералы, например, тип Boolean имеет литералы True и False, а тип Char имеет 256 литералов, представляющих ASCII символы. Функциональный тип также имеет свои литералы, которые являются ничем иным, как безымянными функциями. Функциональные литералы называются лямбда-абстракциями (это название появилось из лямбда-исчисления Черча) или просто лямбдами. Например, для получения списка кубов можно воспользоваться записью

L3 = map (x -> x * x * x) [1, 2, 3, 4] -- Результат - Список [1, 8, 27, 64]

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

Sum1:: (Int, Int) ->Int

Sum1 (n, m) = n + m

Sum2:: Int ->Int ->Int

Sum2 n m = n + m

Вопреки первому впечатлению функция sum1 принимает всего один аргумент - пару чисел, и возвращает результат - их сумму. Функция sum2 (эквивалентная стандартному оператору (+)) - пример частично вычисляемой функции. Эта функция принимает в качестве аргумента число (типа Int) и возвращает Функцию прибавляющую это число к своему аргументу. Зачем это нужно? Функция sum2 позволяет легко определять свои частные случаи. Например - функция инкремент, увеличивающая свой аргумент на 1 определяется как частный случай sum2 следующим образом:

Inc:: Int ->Int

Inc = sum2 1

Функция map - тоже пример частично-вычисляемой функции. Эта функция принимает в качестве аргумента функцию и возвращает функцию принимающую список и возвращающую другой список. Это легко понять если взглянуть на пример:

    -- Sins Принимает Список Действительных Чисел (типа Double) -- И Возвращает Список Их Синусов

Sins:: [Double] -> [Double]

Sins = mapsin

Похожие статьи




Модульность - Функциональные языки программирования

Предыдущая | Следующая