1 / 14

Функциональное программирование

Функциональное программирование. Факультет инноваций и высоких технологий Московский физико-технический институт. Лекция 1 9. Последовательности и ленивые вычисления в F#. Мемоизация. F# Sequences. F# предоставляет механизм для реализации таких вычислений – sequences.

kyoko
Télécharger la présentation

Функциональное программирование

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Функциональное программирование Факультет инноваций и высоких технологий Московский физико-технический институт

  2. Лекция 19 Последовательности и ленивые вычисления в F#. Мемоизация.

  3. F# Sequences • F# предоставляет механизм для реализации таких вычислений – sequences let fibs = Seq.unfold (fun (u,v) -> Some(u,(u+v,u))) (1,1);; Seq.take 10 fibs;; fibs;; let squares = Seq.init_infinite(fun n -> n*n);; let squares10 = Seq.init_finite 10 (fun n -> n*n);; • Seqне кеширует результаты вычислений(аналог IEnumerable) • LazyList – аналогичен Seq, но кеширует результаты

  4. Пример: вычисление Pi S/A=Pi*R2/4/R2=H/M public double area(double p) { var R = new Random(); int max = 10000; int hits = 0; for (var i = 0; i < max; i++) { var x = R.NextDouble() * p; var y = R.NextDouble() * p; if (x * x + y * y <= p * p) hits++; } return 4 * p * p * hits / max; }

  5. Пример: Метод Монте-Карло let rand max n = Seq.generate (fun () -> new System.Random(n)) (fun r -> Some(r.NextDouble()*max)) (fun _ -> ());; let MonteCarlo hit max iters = let hits = (float)( Seq.zip (rand max 1) (rand max 3) |> Seq.take iters |> Seq.filter hit |> Seq.length) in 4.0*max*max*hits/((float)iters);; let area radius = MonteCarlo (fun (x,y) -> x*x+y*y<=radius*radius) radius 100000;; let Pi = (area 10.0)/100.0;;

  6. Пример: чтение из файла #light open System.IO let ReadLines fn = seq { use inp = File.OpenText fn in while not(inp.EndOfStream) do yield (inp.ReadLine()) };; let table = ReadLines "csvsample.txt" |> Seq.map (fun s -> s.Split([|','|]));; let nstuds = table |> Seq.fold (fun x l -> if l.[0]="Y" then x+1 else x) 0;;

  7. Частотный словарь let FreqDict S = Seq.fold ( fun (ht:Map<_,int>) v -> if Map.mem v ht then Map.add v ((Map.find v ht)+1) ht else Map.add v 1 ht) (Map.empty) S;; ReadLines "prince.txt" |> Seq.map_concat (fun s -> s.Split([|',';' ';':';'!';'.'|])) |> FreqDict |> Map.to_list |> List.sort(fun (k1,v1) (k2,v2) -> -compare v1 v2) |> List.filter(fun (k,v) -> k.Length>3) |> Seq.take 10;;

  8. Ленивые вычисления • F# - язык с энергичной стратегией вычислений • Ленивость реализуется с помощью • Seq / LazyList • lazy / force • let expr = lazy expr – формирует значение типа Lazy<‘a> • force : Lazy<T> → T – форсирует вычисление значения

  9. Ленивый факториал let rec lazy_fact n = let _ = printfn "Apply %d" n in match n with 1 -> lazy 1 | n -> lazy (n*Lazy.force (lazy_fact(n-1)));; let rec lazy_fact n = lazy( let _ = printfn "Apply %d" n in match n with 1 -> 1 | n -> n*lazy_fact(n-1).Force());; > let f = lazy_fact 5;; val f : Lazy<int> Apply 5 > f;; val it : Lazy<int> = {status = Delayed;} > Lazy.force f;; Apply 4 Apply 3 Apply 2 Apply 1 val it : int = 120 > f;; val it : Lazy<int> = {status = Value;}

  10. Последовательности и ленивые вычисления • Ленивая последовательность типа Sequence может быть смоделирована на энергичном языке с использованием примитивов lazy и force. type 'a SeqCell = Nil | Cons of 'a * 'a Stream and 'a Stream = Lazy<'a SeqCell>;; let sample1 = lazy(Cons(1,lazy(Cons(2,lazy(Nil)))));; let sample2 = lazy(Cons(3,lazy(Cons(4,lazy(Nil)))));; let rec concat s t = lazy( match Lazy.force s with Nil -> Lazy.force t | Cons(x,y) -> Cons(x,concat y t));;

  11. Мемоизация • Техника явной мемоизации может быть введена при энергичных вычислениях let rec fib n = if n<2 then 1 else fib (n-1) + fib(n-2);; open System.Collections.Generic let mfib = let d = new Dictionary<int,int>() let rec fib n = if d.ContainsKey(n) then d.[n] else let res = if n<2 then 1 else fib (n-1) + fib(n-2) d.Add(n,res) res fun n -> fib n;; > time (fun() -> fib 20);; Execution took 00:00:00.4000 > time (fun() -> mfib 20);; Execution took 00:00:00.0020

  12. Генерализация мемоизации • В ленивых языках с автоматической мемоизацией рекурсивное вычисление чисел Фибоначчи приобретает линейную сложность! let memoize (f: 'a -> 'b) = let t = newDictionary<'a,'b>() fun n -> if t.ContainsKey(n) then t.[n] else let res = f n t.Add(n,res) res;; let rec fibFast = memoize ( fun n -> if n < 2 then 1 else fibFast(n-1) + fibFast(n-2));;

  13. Эффект от ускорения

  14. Мораль • Чистое лямбда-исчисление может рассматриваться как язык программирования • Оно определяет некоторый счетный класс вычислимых функций • После нескольких синтаксических улучшений язык становится почти удобным • В функциональном программировании для хранения данных и частичных вычислений важно понятие замыкания: функции + контекста на момент ее определения • Ленивые вычисления – позволяют работать с бесконечными структурами данных + делают некоторые алгоритмы более эффективными

More Related