Update samples.
[fsharp-ref.git] / FSharpRef / Functional.fs
1 module Functional
2
3 open System.IO
4 open System.Linq
5
6 // Write something on a file.
7 let appendFile (filename: string) (text: string) =
8 use sw = new StreamWriter(filename, true)
9 sw.WriteLine(text)
10
11 // Recursive function.
12 let rec fac n =
13 if n <= 1 then 1
14 else n * fac (n - 1)
15
16 // Mutual recursive functions.
17 let rec isEven n =
18 if n = 0 then true
19 elif n = 1 then false
20 else isOdd (n - 1)
21 and isOdd n =
22 if n = 0 then false
23 elif n = 1 then true
24 else isEven (n - 1)
25
26 // Algebraic data type.
27 type Suit =
28 | Diamond
29 | Spade
30 | Heart
31 | Club
32
33 type PlayingCard =
34 | Ace of Suit
35 | King of Suit
36 | Queen of Suit
37 | Jack of Suit
38 | NumCard of int * Suit
39 member this.Value = // Property.
40 match this with
41 | Ace (_) -> 14
42 | King (_) -> 13
43 | Queen (_) -> 12
44 | Jack (_) -> 11
45 | NumCard (n, _) when n >= 2 && n <= 10 -> n
46 | NumCard (_) -> failwith "Card has invalid value!"
47
48 let deckOfCards =
49 [
50 for suit in [ Spade; Club; Heart; Diamond ] do
51 yield Ace(suit)
52 yield King(suit)
53 yield Queen(suit)
54 yield Jack(suit)
55 for n in [2 .. 10] do
56 yield NumCard(n, suit)
57 ]
58
59 // Records with custom equality.
60 [<CustomEquality; NoComparison>]
61 type Person =
62 { First: string; Last: string; Age: int }
63 override this.Equals(other) =
64 match other with
65 | :? Person as p -> p.First = this.First && p.Last = this.Last
66 | _ -> false
67 override this.GetHashCode() =
68 this.First.GetHashCode() ^^^ this.Last.GetHashCode()
69
70 let steve = { First = "Steve"; Last = "Holt"; Age = 17 }
71 let stevesTwin = { steve with First = "Paul" }
72
73 // Queries. Should be used with SQL or other external data sources.
74 let youngPersonNames persons =
75 query {
76 for p in persons do
77 where (p.Age < 15)
78 select p.First
79 }
80
81 // Infinite lazy sequence.
82 let allPositiveInts =
83 seq {
84 for i in 1 .. System.Int32.MaxValue do
85 yield i
86 }
87 let rec fibs x y =
88 seq {
89 yield x
90 yield! fibs y (x + y)
91 }
92 let testYieldBang =
93 seq {
94 yield 10
95 yield! [1; 2; 3] // Yields a collection.
96 }
97 // Generator.
98 let testUnfold =
99 Seq.unfold (fun a -> if a > 10 then None else Some(10 * a, a + 1)) 1
100
101 // Functions composition.
102 let SizeOfFolder =
103 let getFiles folder =
104 Directory.GetFiles(folder, "*.*", SearchOption.AllDirectories)
105 getFiles
106 >> Array.map (fun file -> (new FileInfo(file)).Length)
107 >> Array.sum
108
109 // Matches literals.
110 [<Literal>]
111 let Bill = "Bill Gates" // Must begin with a capital!
112 let greet name =
113 match name with
114 | Bill -> "Hello rich Bill!"
115 | name -> sprintf "Hello poor %s" name
116
117 // Matches tuples.
118 let testXor x y =
119 match x, y with
120 | a, b when a <> b -> true
121 | _ -> false