// Code from Hansen and Rischel: Functional Programming using F# 16/12 2012 // Chapter 11: Sequences // Code from the Sections 11.1 - 11.7 // From Section 11.1: The sequence concept in F# let nat = Seq.initInfinite (fun i -> i);; Seq.nth 5 nat;; let idWithPrint i = printfn "%d" i i;; let natWithPrint = Seq.initInfinite idWithPrint;; let natWithPrintCached = Seq.cache natWithPrint;; // From Section 11.2: Some operations on sequences let s1 = Seq.append (seq [1;2;3;4]) (seq [5;6]);; let s2 = Seq.append nat s1;; let s3 = Seq.append s1 nat;; (Seq.nth 2 s3 = Seq.nth 2 s1) && (Seq.nth 10 s3 = Seq.nth (10-6) nat);; let cons x sq = Seq.append (Seq.singleton x) sq;; // From Section 11.3: Delays, Recursion and Side-effects let rec from i = cons i (from(i+1));; let rec from1 i = cons i (Seq.delay (fun () -> from1(i+1)));; let rec from2 i = Seq.delay (fun () -> cons i (from2(i+1)));; // BØR RETTES PÅ SIDE 257 let rec fromWithPrint1 i = cons (idWithPrint i) (Seq.delay (fun () -> fromWithPrint1(i+1)));; // SKAL RETTES PÅ SIDE 257 let rec fromWithPrint2 i = Seq.delay (fun () -> cons (idWithPrint i) (fromWithPrint2(i+1)));; // From Section 11.4: Example: Sieve of Eratosthenes let sift a sq = Seq.filter (fun n -> n % a <> 0) sq;; let rec sieve sq = Seq.delay (fun () -> let p = Seq.nth 0 sq cons p (sieve(sift p (Seq.skip 1 sq))));; let primes = sieve (Seq.initInfinite (fun n -> n+2));; let nthPrime n = Seq.nth n primes;; let primesCached = Seq.cache primes;; let nthPrime1 n = Seq.nth n primesCached;; let rec sieve1 sq = Seq.cache (Seq.delay (fun () -> let p = Seq.nth 0 sq cons p (sieve1(sift p (Seq.skip 1 sq)))));; // From Section 11.5: Limits of sequences: Newton-Raphson Approximations let next a x = (a/x + x)/2.0;; let rec iter f x = function | 0 -> x | n -> iter f (f x) (n-1);; let iterate f x = Seq.initInfinite (fun i -> iter f x i);; // We copy enumerator declaration from Chapter 8 open System.Collections.Generic;; let enumerator (m: IEnumerable<'c>) = let e = ref (m.GetEnumerator()) let f () = match (!e).MoveNext() with | false -> None | _ -> Some ((!e).Current) f;; let rec inTolerance (eps:float) sq = let f = enumerator sq let nextVal() = Option.get(f()) let rec loop a = let b = nextVal() if abs(a-b) > eps then loop b else a loop(nextVal());; let sRoot a = inTolerance 1E-6 (iterate (next a) 1.0);; sRoot 2.0;; // From Section 11.6: Sequence expressions let rec from3 i = seq {yield i yield! from3 (i+1)};; let sift1 a sq = seq {for n in sq do if n % a <> 0 then yield n };; let rec sieve2 sq = seq {let p = Seq.nth 0 sq yield p yield! sieve2(sift1 p (Seq.skip 1 sq)) };; let primes1 = sieve2(Seq.initInfinite (fun n -> n+2));; // SKAL RETTES PÅ SIDE 264 open System.IO;; // Should be adapted appropriately to suit your own catalogues Directory.SetCurrentDirectory @"C:\mrh\Forskning\Cambridge\";; let rec allFiles dir = seq { yield! Directory.GetFiles dir yield! Seq.collect allFiles (Directory.GetDirectories dir)};; // The captureSingle function from the TextProcessing library (Appendix B) is copied here open System.Text.RegularExpressions;; let captureSingle (ma:Match) (n:int) = ma.Groups.[n].Captures.[0].Value ;; let rec searchFiles files exts = let reExts = List.foldBack (fun ext re -> ext+"|"+re) exts "" let re = Regex (@"\G(\S*\\)([^\\]+)\.(" + reExts + ")$") seq {for fn in files do let m = re.Match fn if m.Success then let path = captureSingle m 1 let name = captureSingle m 2 let ext = captureSingle m 3 yield (path, name, ext) };; let funFiles = Seq.cache (searchFiles (allFiles ".") ["fs";"fsi"]);; // From Section 11.7: Specializations of sequences let squares = seq {for i in 0..10 do yield i*i };; let evenUpTo n = seq [0..2.. n];;