110 likes | 300 Views
Функциональное программирование. Факультет инноваций и высоких технологий Московский физико-технический институт. Лекция 11. Функциональные структуры данных. Функциональные структуры данных.
E N D
Функциональное программирование Факультет инноваций и высоких технологий Московский физико-технический институт
Лекция 11 Функциональные структуры данных
Функциональные структуры данных • В зависимости от решаемых задач для эффективного решения приходится использовать специфические структуры данных • Chris Okasaki, Purely Functional Data Structures, 1996.
Очередь • Наивная реализация • head / tail – вставка в начало – O(1) • put – вставка в конец – O(n) type 'a queue = 'a list;; let rec put x = function [] -> [x] | h::t -> h::snoc x t;; // hd, tl – the same as for List
Реализация с двумя списками • Два списка • 1,2,3,4,5 => [1,2,3],[5,4] • Добавляем ко второму, берем из первого • Если первый становится пустым – перестраиваем • Первый список пустой только для пустой очереди • Все операции – O(1) [не считая периодической перестройки] type 'a queue = 'a list * 'a list;; let tail (L,R) = match L with [x] -> (rev R, []) | h::t -> (t,R);; let head (h::_,_) = h;; let put x (L,R) = match L with [] -> ([x],R) | _ -> (L,x::R) ;;
Массивы F# • F# - частично-императивный язык, содержит mutable-типы данных • Тип массив (T []) во многом напоминает список, но является mutable: • Операции не возвращают новый массив, а модифицируют исходный • Соответствует массивам .NET (интероперабельны с ними) let a = [|1;2;3|];; a.[1];; a.[1] <- 4;; a.[1..2];; a.[..2];; let incr a = for i=0 to Array.length a-1 do a.[i] <- a.[i]+1 done;; let incr a = Array.iteri (fun i x -> a.[i] <- a.[i]+1) a;;
Типы .NET Framework • При программировании на F# бывает удобно использовать типы, определенные в .NET Framework • Они почти всегда mutable, но можно их использовать в immutable-контексте • Полезно знать: • ResizeArray – соответствует List<T> в .NET • Dictionary <T1,T2>
Пример • Вычисление треугольника Паскаля 1 1 1 2 1 1 3 3 1 1 4 6 4 1 ....... let pascal n = let rec pas L n = let A::t = L in if n = 0 then L else pas (( (1:: [for i=1 to length A-1 -> A.[i-1]+A.[i]]) @[1]) ::L) (n-1) in pas [[1;1]] n;;
Мораль • Рекурсивные структуры данных – часто используемый удобный механизм хранения данных в функциональном программировании • Списки – гармоничная часть языка • Прозрачный синтаксис (специальный синтаксис конструкторов) • Поддержка со стороны библиотеки • Множество абстрактных функций для обработки списков позволяет, комбинируя их, легко реализовывать различные алгоритмы обработки