~ubuntu-branches/ubuntu/trusty/fsharp/trusty

« back to all changes in this revision

Viewing changes to debian/tests/BasicXBuildTest/Tutorial.fs

  • Committer: Package Import Robot
  • Author(s): Christopher James Halse Rogers
  • Date: 2014-02-13 16:55:16 UTC
  • mfrom: (3.1.2 trusty)
  • Revision ID: package-import@ubuntu.com-20140213165516-o51ftovy7pu2d0rk
Tags: 3.0.34+dfsg-3ubuntu1
* Make DEP-8 test depend on only fsharp package to pick up any dependency breakage
* Add missing libmono-compilerservices-symbolwriter4.0-cil dependency to fsharp
* Add fsharpc/fsharpi manpages
* Strip executable bit from xbuild .Targets files; now lintian clean!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//  Author:
 
2
//       Christohper James Halse Rogers <raof@ubuntu.com>
 
3
//
 
4
//  Copyright © 2014 Christopher James Halse Rogers <raof@ubuntu.com>
 
5
//
 
6
//  This program is free software: you can redistribute it and/or modify
 
7
//  it under the terms of the GNU Lesser General Public License as published by
 
8
//  the Free Software Foundation, either version 3 of the License, or
 
9
//  (at your option) any later version.
 
10
//
 
11
//  This program is distributed in the hope that it will be useful,
 
12
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
//  GNU Lesser General Public License for more details.
 
15
//
 
16
//  You should have received a copy of the GNU Lesser General Public License
 
17
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
 
 
19
// This sample will guide you through elements of the F# language. 
 
20
//
 
21
// *******************************************************************************************************
 
22
//   To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click
 
23
//   and select "Execute in Interactive".  You can open the F# Interactive Window from the "View" menu.
 
24
// *******************************************************************************************************
 
25
//
 
26
// For more about F#, see:
 
27
//     http://fsharp.net
 
28
//
 
29
// For additional templates to use with F#, see the 'Online Templates' in Visual Studio,
 
30
//     'New Project' --> 'Online Templates'
 
31
//
 
32
// For specific F# topics, see:
 
33
//     http://fsharp.org (F# Open Organization)
 
34
//     http://tryfsharp.org (F# Learning Portal)
 
35
//     http://go.microsoft.com/fwlink/?LinkID=234174 (Visual F# Development Portal)
 
36
//     http://go.microsoft.com/fwlink/?LinkID=124614 (Visual F# Code Gallery)
 
37
//     http://go.microsoft.com/fwlink/?LinkId=235173 (Visual F# Math/Stats Programming)
 
38
//     http://go.microsoft.com/fwlink/?LinkId=235176 (Visual F# Charting)
 
39
 
 
40
 
 
41
// Contents:
 
42
 
 
43
//    - Integers and basic functions
 
44
//    - Booleans
 
45
//    - Strings
 
46
//    - Tuples
 
47
//    - Lists and list processing
 
48
//    - Classes
 
49
//    - Generic classes
 
50
//    - Implementing interfaces
 
51
//    - Arrays
 
52
//    - Sequences
 
53
//    - Recursive functions
 
54
//    - Record types
 
55
//    - Union types
 
56
//    - Option types           
 
57
//    - Pattern matching       
 
58
//    - Units of measure       
 
59
//    - Parallel array programming
 
60
//    - Using events
 
61
//    - Database access using type providers
 
62
//    - OData access using type providers
 
63
 
 
64
 
 
65
// ---------------------------------------------------------------
 
66
//         Integers and basic functions
 
67
// ---------------------------------------------------------------
 
68
 
 
69
module Integers =
 
70
    let sampleInteger = 176
 
71
 
 
72
    /// Do some arithmetic starting with the first integer
 
73
    let sampleInteger2 = (sampleInteger/4 + 5 - 7) * 4
 
74
 
 
75
    /// A list of the numbers from 0 to 99
 
76
    let sampleNumbers = [ 0 .. 99 ]
 
77
 
 
78
    /// A list of all tuples containing all the numbers from 0 to 99 and their squares
 
79
    let sampleTableOfSquares = [ for i in 0 .. 99 -> (i, i*i) ]
 
80
 
 
81
    // The next line prints a list that includes tuples, using %A for generic printing
 
82
    printfn "The table of squares from 0 to 99 is:\n%A" sampleTableOfSquares
 
83
 
 
84
 
 
85
module BasicFunctions =
 
86
 
 
87
    // Use 'let' to define a function that accepts an integer argument and returns an integer.
 
88
    let func1 x = x*x + 3            
 
89
 
 
90
    // Parenthesis are optional for function arguments
 
91
    let func1a (x) = x*x + 3            
 
92
 
 
93
 
 
94
    /// Apply the function, naming the function return result using 'let'.
 
95
    /// The variable type is inferred from the function return type.
 
96
    let result1 = func1 4573
 
97
 
 
98
    printfn "The result of squaring the integer 4573 and adding 3 is %d" result1
 
99
 
 
100
    // When needed, annotate the type of a parameter name using '(argument:type)'
 
101
    let func2 (x:int) = 2*x*x - x/5 + 3
 
102
 
 
103
    let result2 = func2 (7 + 4)
 
104
 
 
105
    printfn "The result of applying the 1st sample function to (7 + 4) is %d" result2
 
106
 
 
107
 
 
108
    let func3 x =
 
109
        if x < 100.0 then
 
110
            2.0*x*x - x/5.0 + 3.0
 
111
        else
 
112
            2.0*x*x + x/5.0 - 37.0
 
113
 
 
114
    let result3 = func3 (6.5 + 4.5)
 
115
 
 
116
    printfn "The result of applying the 2nd sample function to (6.5 + 4.5) is %f" result3
 
117
 
 
118
 
 
119
// ---------------------------------------------------------------
 
120
//         Booleans
 
121
// ---------------------------------------------------------------
 
122
 
 
123
 
 
124
module SomeBooleanValues =
 
125
 
 
126
    let boolean1 = true
 
127
 
 
128
    let boolean2 = false
 
129
 
 
130
    let boolean3 = not boolean1 && (boolean2 || false)
 
131
 
 
132
    printfn "The expression 'not boolean1 && (boolean2 || false)' is %A" boolean3
 
133
 
 
134
 
 
135
 
 
136
// ---------------------------------------------------------------
 
137
//         Strings
 
138
// ---------------------------------------------------------------
 
139
 
 
140
 
 
141
module StringManipulation =
 
142
 
 
143
    let string1 = "Hello"
 
144
 
 
145
    let string2  = "world"
 
146
 
 
147
    /// Use @ to create a verbatim string literal
 
148
 
 
149
    let string3 = @"c:\Program Files\"
 
150
 
 
151
    /// Using a triple-quote string literal
 
152
    let string4 = """He said "hello world" after you did"""
 
153
 
 
154
    let helloWorld = string1 + " " + string2 // concatenate the two strings with a space in between
 
155
 
 
156
    printfn "%s" helloWorld
 
157
 
 
158
    /// A string formed by taking the first 7 characters of one of the result strings
 
159
    let substring = helloWorld.[0..6]
 
160
 
 
161
    printfn "%s" substring
 
162
 
 
163
 
 
164
 
 
165
// ---------------------------------------------------------------
 
166
//         Tuples (ordered sets of values)
 
167
// ---------------------------------------------------------------
 
168
 
 
169
module Tuples =
 
170
 
 
171
    /// A simple tuple of integers
 
172
    let tuple1 = (1, 2, 3)
 
173
 
 
174
    /// A function that swaps the order of two values in a tuple.
 
175
    /// QuickInfo shows that the function is inferred to have a generic type.
 
176
 
 
177
    let swapElems (a, b) = (b, a)
 
178
 
 
179
    printfn "The result of swapping (1, 2) is %A" (swapElems (1,2))
 
180
 
 
181
    /// A tuple consisting of an integer, a string, and a double-precision floating point number
 
182
    let tuple2 = (1, "fred", 3.1415)
 
183
 
 
184
    printfn "tuple1: %A    tuple2: %A" tuple1 tuple2 
 
185
 
 
186
 
 
187
 
 
188
// ---------------------------------------------------------------
 
189
//         Lists and list processing
 
190
// ---------------------------------------------------------------
 
191
 
 
192
module Lists =
 
193
 
 
194
    let list1 = [ ]            /// an empty list
 
195
    
 
196
    let list2 = [ 1; 2; 3 ]    /// list of 3 elements
 
197
 
 
198
    let list3 = 42 :: list2    /// a new list with '42' added to the beginning
 
199
 
 
200
    let numberList = [ 1 .. 1000 ]  /// list of integers from 1 to 1000
 
201
 
 
202
    /// A list containing all the days of the year
 
203
    let daysList =
 
204
        [ for month in 1 .. 12 do
 
205
              for day in 1 .. System.DateTime.DaysInMonth(2012, month) do
 
206
                  yield System.DateTime(2012, month, day) ]
 
207
 
 
208
    /// A list containing the tuples which are the coordinates of the black squares on a chess board.
 
209
    let blackSquares =
 
210
 
 
211
        [ for i in 0 .. 7 do
 
212
              for j in 0 .. 7 do
 
213
                  if (i+j) % 2 = 1 then
 
214
                      yield (i, j) ]
 
215
 
 
216
    /// Square the numbers in numberList, using the pipeline operator to pass an argument to List.map   
 
217
    let squares =
 
218
        numberList
 
219
        |> List.map (fun x -> x*x)
 
220
 
 
221
    /// Computes the sum of the squares of the numbers divisible by 3.
 
222
    let sumOfSquaresUpTo n =
 
223
        numberList
 
224
        |> List.filter (fun x -> x % 3 = 0)
 
225
        |> List.sumBy (fun x -> x * x)
 
226
 
 
227
 
 
228
 
 
229
 
 
230
// ---------------------------------------------------------------
 
231
//         Classes
 
232
// ---------------------------------------------------------------
 
233
 
 
234
 
 
235
module DefiningClasses =
 
236
    /// The class's constructor takes two arguments: dx and dy, both of type 'float'.
 
237
    type Vector2D(dx : float, dy : float) =
 
238
 
 
239
        /// The length of the vector, computed when the object is constructed
 
240
        let length = sqrt (dx*dx + dy*dy)
 
241
 
 
242
 
 
243
        // 'this' specifies a name for the object's self identifier
 
244
        // In instance methods, it must appear before the member name.
 
245
 
 
246
        member this.DX = dx 
 
247
 
 
248
        member this.DY = dy
 
249
 
 
250
        member this.Length = length
 
251
 
 
252
        member this.Scale(k) = Vector2D(k * this.DX, k * this.DY)
 
253
 
 
254
   
 
255
    /// An instance of the Vector2D class
 
256
    let vector1 = Vector2D(3.0, 4.0)
 
257
 
 
258
    /// Get a new scaled vector object, without modifying the original object
 
259
    let vector2 = vector1.Scale(10.0)
 
260
 
 
261
    printfn "Length of vector1: %f      Length of vector2: %f" vector1.Length vector2.Length
 
262
 
 
263
 
 
264
 
 
265
// ---------------------------------------------------------------
 
266
//         Generic classes
 
267
// ---------------------------------------------------------------
 
268
 
 
269
module DefiningGenericClasses =
 
270
 
 
271
    type StateTracker<'T>(initialElement: 'T) = // 'T is the type parameter for the class
 
272
 
 
273
        /// Store the states in an array
 
274
        let mutable states = [ initialElement ]
 
275
 
 
276
        /// Add a new element to the list of states
 
277
        member this.UpdateState newState =
 
278
            states <- newState :: states  // use the '<-' operator to mutate the value
 
279
 
 
280
 
 
281
        /// Get the entire list of historical states
 
282
        member this.History = states
 
283
 
 
284
 
 
285
        /// Get the latest state
 
286
        member this.Current = states.Head
 
287
 
 
288
 
 
289
    /// An 'int' instance of the state tracker class. Note that the type parameter is inferred.
 
290
    let tracker = StateTracker 10
 
291
 
 
292
 
 
293
    // Add a state
 
294
    tracker.UpdateState 17
 
295
 
 
296
 
 
297
 
 
298
// ---------------------------------------------------------------
 
299
//         Implementing interfaces
 
300
// ---------------------------------------------------------------
 
301
 
 
302
/// Type that implements IDisposable
 
303
 
 
304
type ReadFile() =
 
305
 
 
306
    let file = new System.IO.StreamReader("readme.txt")
 
307
 
 
308
    member this.ReadLine() = file.ReadLine()
 
309
 
 
310
    // this class's implementation of IDisposable members
 
311
    interface System.IDisposable with   
 
312
 
 
313
        member this.Dispose() = file.Close()
 
314
 
 
315
 
 
316
// ---------------------------------------------------------------
 
317
//         Arrays
 
318
// ---------------------------------------------------------------
 
319
 
 
320
 
 
321
module Arrays =
 
322
 
 
323
 
 
324
    /// The empty array
 
325
    let array1 = [| |]
 
326
 
 
327
    let array2 = [| "hello"; "world"; "and"; "hello"; "world"; "again" |]
 
328
 
 
329
    let array3 = [| 1 .. 1000 |]
 
330
 
 
331
    /// An array containing only the words "hello" and "world"
 
332
 
 
333
    let array4 = [| for word in array2 do
 
334
                        if word.Contains("l") then
 
335
                            yield word |]
 
336
 
 
337
 
 
338
    /// An array initialized by index and containing the even numbers from 0 to 2000
 
339
    let evenNumbers = Array.init 1001 (fun n -> n * 2)
 
340
 
 
341
    /// sub-array extracted using slicing notation
 
342
    let evenNumbersSlice = evenNumbers.[0..500]
 
343
 
 
344
    for word in array4 do
 
345
        printfn "word: %s" word
 
346
 
 
347
    // modify an array element using the left arrow assignment operator
 
348
    array2.[1] <- "WORLD!"
 
349
 
 
350
    /// Calculates the sum of the lengths of the words that start with 'h'
 
351
    let sumOfLengthsOfWords =
 
352
        array2
 
353
        |> Array.filter (fun x -> x.StartsWith "h")
 
354
        |> Array.sumBy (fun x -> x.Length)
 
355
 
 
356
 
 
357
// ---------------------------------------------------------------
 
358
//         Sequences
 
359
// ---------------------------------------------------------------
 
360
 
 
361
 
 
362
module Sequences =
 
363
 
 
364
    // Sequences are evaluated on-demand and are re-evaluated each time they are iterated.
 
365
    // An F# sequence is an instance of a System.Collections.Generic.IEnumerable<'T>,
 
366
    // so Seq functions can be applied to Lists and Arrays as well.
 
367
 
 
368
    /// The empty sequence
 
369
    let seq1 = Seq.empty
 
370
 
 
371
    let seq2 = seq { yield "hello"; yield "world"; yield "and"; yield "hello"; yield "world"; yield "again" }
 
372
 
 
373
    let numbersSeq = seq { 1 .. 1000 }
 
374
 
 
375
    /// another array containing only the words "hello" and "world"
 
376
    let seq3 =
 
377
        seq { for word in seq2 do
 
378
                  if word.Contains("l") then
 
379
                      yield word }
 
380
 
 
381
 
 
382
    let evenNumbers = Seq.init 1001 (fun n -> n * 2)
 
383
 
 
384
    let rnd = System.Random()
 
385
 
 
386
    /// An infinite sequence which is a random walk
 
387
    //  Use yield! to return each element of a subsequence, similar to IEnumerable.SelectMany.
 
388
 
 
389
    let rec randomWalk x =
 
390
        seq { yield x
 
391
              yield! randomWalk (x + rnd.NextDouble() - 0.5) }
 
392
 
 
393
 
 
394
    let first100ValuesOfRandomWalk =
 
395
        randomWalk 5.0
 
396
        |> Seq.truncate 100
 
397
        |> Seq.toList
 
398
 
 
399
 
 
400
// ---------------------------------------------------------------
 
401
//         Recursive functions
 
402
// ---------------------------------------------------------------
 
403
 
 
404
 
 
405
module RecursiveFunctions  =
 
406
 
 
407
    /// Compute the factorial of an integer. Use 'let rec' to define a recursive function
 
408
    let rec factorial n =
 
409
        if n = 0 then 1 else n * factorial (n-1)
 
410
 
 
411
    /// Computes the greatest common factor of two integers.
 
412
    //  Since all of the recursive calls are tail calls, the compiler will turn the function into a loop,
 
413
    //  which improves performance and reduces memory consumption.
 
414
 
 
415
    let rec greatestCommonFactor a b =                      
 
416
        if a = 0 then b
 
417
        elif a < b then greatestCommonFactor a (b - a)          
 
418
        else greatestCommonFactor (a - b) b
 
419
 
 
420
 
 
421
    /// Computes the sum of a list of integers using recursion.
 
422
    let rec sumList xs =
 
423
        match xs with
 
424
        | []    -> 0
 
425
        | y::ys -> y + sumList ys
 
426
 
 
427
 
 
428
    /// Make the function tail recursive, using a helper function with a result accumulator
 
429
    let rec private sumListTailRecHelper accumulator xs =
 
430
        match xs with
 
431
        | []    -> accumulator
 
432
        | y::ys -> sumListTailRecHelper (accumulator+y) ys
 
433
 
 
434
 
 
435
    let sumListTailRecursive xs = sumListTailRecHelper 0 xs
 
436
 
 
437
 
 
438
 
 
439
// ---------------------------------------------------------------
 
440
//         Record types
 
441
// ---------------------------------------------------------------
 
442
 
 
443
 
 
444
module RecordTypes =
 
445
    // define a record type
 
446
    type ContactCard =
 
447
        { Name     : string
 
448
          Phone    : string
 
449
          Verified : bool }
 
450
 
 
451
    let contact1 = { Name = "Alf" ; Phone = "(206) 555-0157" ; Verified = false }
 
452
 
 
453
    // Create a new record that is a copy of contact1,
 
454
    // but has different values for the 'Phone' and 'Verified' fields
 
455
 
 
456
    let contact2 = { contact1 with Phone = "(206) 555-0112"; Verified = true }
 
457
 
 
458
 
 
459
    /// Converts a 'ContactCard' object to a string
 
460
    let showCard c =
 
461
        c.Name + " Phone: " + c.Phone + (if not c.Verified then " (unverified)" else "")
 
462
 
 
463
       
 
464
// ---------------------------------------------------------------
 
465
//         Union types
 
466
// ---------------------------------------------------------------
 
467
 
 
468
module UnionTypes =
 
469
 
 
470
    /// Represents the suit of a playing card
 
471
    type Suit =
 
472
        | Hearts
 
473
        | Clubs
 
474
        | Diamonds
 
475
        | Spades
 
476
 
 
477
    /// Represents the rank of a playing card
 
478
    type Rank =
 
479
        /// Represents the rank of cards 2 .. 10
 
480
        | Value of int
 
481
        | Ace
 
482
        | King
 
483
        | Queen
 
484
        | Jack
 
485
 
 
486
        static member GetAllRanks() =
 
487
            [ yield Ace
 
488
              for i in 2 .. 10 do yield Value i
 
489
              yield Jack
 
490
              yield Queen
 
491
              yield King ]
 
492
 
 
493
    type Card =  { Suit: Suit; Rank: Rank }
 
494
 
 
495
    /// Returns a list representing all the cards in the deck
 
496
 
 
497
    let fullDeck =
 
498
        [ for suit in [ Hearts; Diamonds; Clubs; Spades] do
 
499
              for rank in Rank.GetAllRanks() do
 
500
                  yield { Suit=suit; Rank=rank } ]
 
501
 
 
502
 
 
503
    /// Converts a 'Card' object to a string
 
504
    let showCard c =
 
505
        let rankString =
 
506
            match c.Rank with
 
507
            | Ace -> "Ace"
 
508
            | King -> "King"
 
509
            | Queen -> "Queen"
 
510
            | Jack -> "Jack"
 
511
            | Value n -> string n
 
512
 
 
513
        let suitString =
 
514
            match c.Suit with
 
515
            | Clubs -> "clubs"
 
516
            | Diamonds -> "diamonds"
 
517
            | Spades -> "spades"
 
518
            | Hearts -> "hearts"
 
519
 
 
520
        rankString  + " of " + suitString
 
521
 
 
522
    let printAllCards() =
 
523
        for card in fullDeck do
 
524
            printfn "%s" (showCard card)
 
525
 
 
526
 
 
527
 
 
528
// ---------------------------------------------------------------
 
529
//         Option types
 
530
// ---------------------------------------------------------------
 
531
 
 
532
module OptionTypes =
 
533
    /// Option values are any kind of value tagged with either 'Some' or 'None'.
 
534
    /// They are used extensively in F# code to represent the cases where many other
 
535
    /// languages would use null references.
 
536
 
 
537
    type Customer = { zipCode : decimal option }
 
538
 
 
539
    /// Abstract class that computes the shipping zone for the customer's zip code,
 
540
    /// given implementations for the 'GetState' and 'GetShippingZone' abstract methods.
 
541
 
 
542
    [<AbstractClass>]
 
543
 
 
544
    type ShippingCalculator =
 
545
 
 
546
        abstract GetState : decimal -> string option
 
547
 
 
548
        abstract GetShippingZone : string -> int
 
549
 
 
550
        /// Return the shipping zone corresponding to the customer's ZIP code
 
551
        /// Customer may not yet have a ZIP code or the ZIP code may be invalid
 
552
        member this.CustomerShippingZone(customer : Customer) =
 
553
 
 
554
            customer.zipCode |> Option.bind this.GetState |> Option.map this.GetShippingZone
 
555
 
 
556
 
 
557
// ---------------------------------------------------------------
 
558
//         Pattern matching
 
559
// ---------------------------------------------------------------
 
560
 
 
561
module PatternMatching =
 
562
 
 
563
    /// A record for a person's first and last name
 
564
 
 
565
    type Person =   
 
566
        { First : string
 
567
          Last  : string }
 
568
 
 
569
 
 
570
    /// Define a discriminated union of 3 different kinds of employees
 
571
 
 
572
    type Employee =
 
573
        /// Engineer is just herself
 
574
        | Engineer  of Person
 
575
        /// Manager has list of reports
 
576
        | Manager   of Person * list<Employee>            
 
577
        /// Executive also has an assistant
 
578
        | Executive of Person * list<Employee> * Employee 
 
579
 
 
580
    /// Count everyone underneath the employee in the management hierarchy, including the employee
 
581
    let rec countReports(emp : Employee) =
 
582
        1 + match emp with
 
583
            | Engineer(id) ->
 
584
                0
 
585
            | Manager(id, reports) ->
 
586
                reports |> List.sumBy countReports
 
587
            | Executive(id, reports, assistant) ->
 
588
                (reports |> List.sumBy countReports) + countReports assistant
 
589
 
 
590
    /// Find all managers/executives named "Dave" who do not have any reports
 
591
    let rec findDaveWithOpenPosition(emps : Employee list) =
 
592
        emps
 
593
        |> List.filter(function
 
594
                       | Manager({First = "Dave"}, []) -> true       // [] matches the empty list
 
595
                       | Executive({First = "Dave"}, [], _) -> true
 
596
                       | _ -> false)                                 // '_' is a wildcard pattern that matches anything
 
597
                                                                     // this handles the "or else" case
 
598
 
 
599
 
 
600
// ---------------------------------------------------------------
 
601
//         Units of measure
 
602
// ---------------------------------------------------------------
 
603
 
 
604
module UnitsOfMeasure =
 
605
    // Code can be annotated with units of measure when using F# arithmetic over numeric types
 
606
 
 
607
    open Microsoft.FSharp.Data.UnitSystems.SI.UnitNames
 
608
 
 
609
    [<Measure>]
 
610
    type mile =
 
611
 
 
612
        /// Conversion factor mile to meter: meter is defined in SI.UnitNames
 
613
 
 
614
        static member asMeter = 1600.<meter/mile>
 
615
 
 
616
 
 
617
    let d  = 50.<mile>          // Distance expressed using imperial units
 
618
    let d' = d * mile.asMeter   // Same distance expressed using metric system
 
619
 
 
620
    printfn "%A = %A" d d'
 
621
    // let error = d + d'       // Compile error: units of measure do not match
 
622
 
 
623
 
 
624
 
 
625
 
 
626
// ---------------------------------------------------------------
 
627
//         Parallel array programming
 
628
// ---------------------------------------------------------------
 
629
 
 
630
 
 
631
module ParallelArrayProgramming =
 
632
 
 
633
    let oneBigArray = [| 0 .. 100000 |]
 
634
 
 
635
    // do some CPU intensive computation
 
636
    let rec computeSomeFunction x =
 
637
        if x <= 2 then 1
 
638
        else computeSomeFunction (x - 1) + computeSomeFunction (x - 2)
 
639
 
 
640
    // Do a parallel map over a large input array
 
641
    let computeResults() = oneBigArray |> Array.Parallel.map (fun x -> computeSomeFunction (x % 20))
 
642
 
 
643
    printfn "Parallel computation results: %A" (computeResults())
 
644
 
 
645
 
 
646
 
 
647
// ---------------------------------------------------------------
 
648
//         Using events
 
649
// ---------------------------------------------------------------
 
650
 
 
651
module Events =
 
652
 
 
653
    open System
 
654
 
 
655
    // Create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger)
 
656
    let simpleEvent = new Event<int>()
 
657
 
 
658
    // Add handler
 
659
    simpleEvent.Publish.Add(fun x -> printfn "this is handler was added with Publish.Add: %d" x)
 
660
 
 
661
    // Trigger event
 
662
    simpleEvent.Trigger(5)
 
663
 
 
664
    // Create instance of Event that follows standard .NET convention: (sender, EventArgs)
 
665
    let eventForDelegateType = new Event<EventHandler, EventArgs>()   
 
666
 
 
667
 
 
668
    // Add handler
 
669
    eventForDelegateType.Publish.AddHandler(
 
670
        EventHandler(fun _ _ -> printfn "this is handler was added with Publish.AddHandler"))
 
671
 
 
672
 
 
673
    // Trigger event (note that sender argument should be set)
 
674
    eventForDelegateType.Trigger(null, EventArgs.Empty)
 
675
 
 
676
 
 
677
 
 
678
// ---------------------------------------------------------------
 
679
//         Database access using type providers
 
680
// ---------------------------------------------------------------
 
681
 
 
682
module DatabaseAccess =
 
683
 
 
684
    // The easiest way to access a SQL database from F# is to use F# type providers.
 
685
    // Add references to System.Data, System.Data.Linq, and FSharp.Data.TypeProviders.dll.
 
686
    // You can use Server Explorer to build your ConnectionString.
 
687
 
 
688
    (*
 
689
 
 
690
    #r "System.Data"
 
691
    #r "System.Data.Linq"
 
692
    #r "FSharp.Data.TypeProviders"
 
693
 
 
694
    open Microsoft.FSharp.Data.TypeProviders
 
695
 
 
696
    type SqlConnection = SqlDataConnection<ConnectionString = @"Data Source=.\sqlexpress;Initial Catalog=tempdb;Integrated Security=True">
 
697
    let db = SqlConnection.GetDataContext()
 
698
 
 
699
    let table =
 
700
        query { for r in db.Table do
 
701
                select r }
 
702
 
 
703
    *)
 
704
 
 
705
 
 
706
    // You can also use SqlEntityConnection instead of SqlDataConnection, which accesses the database using Entity Framework.
 
707
 
 
708
    ()
 
709
 
 
710
 
 
711
 
 
712
// ---------------------------------------------------------------
 
713
//         OData access using type providers
 
714
// ---------------------------------------------------------------
 
715
 
 
716
module OData =
 
717
 
 
718
    (*
 
719
 
 
720
    open System.Data.Services.Client
 
721
    open Microsoft.FSharp.Data.TypeProviders
 
722
 
 
723
    // Consume demographics population and income OData service from Azure Marketplace.
 
724
    // For more information, see http://go.microsoft.com/fwlink/?LinkId=239712
 
725
 
 
726
    type Demographics = Microsoft.FSharp.Data.TypeProviders.ODataService<ServiceUri = "https://api.datamarket.azure.com/Esri/KeyUSDemographicsTrial/">
 
727
    let ctx = Demographics.GetDataContext()
 
728
 
 
729
    // Sign up for a Azure Marketplace account at https://datamarket.azure.com/account/info
 
730
    ctx.Credentials <- System.Net.NetworkCredential ("<your liveID>", "<your Azure Marketplace Key>")
 
731
 
 
732
    let cities = 
 
733
        query { for c in ctx.demog1 do
 
734
                where (c.StateName = "Washington") }
 
735
 
 
736
    for c in cities do
 
737
        printfn "%A - %A" c.GeographyId c.PerCapitaIncome2010.Value
 
738
 
 
739
    *)
 
740
 
 
741
    ()
 
742
 
 
743
 
 
744
#if COMPILED
 
745
 
 
746
module BoilerPlateForForm =
 
747
    [<System.STAThread>]
 
748
    do ()
 
749
//    do System.Windows.Forms.Application.Run()
 
750
 
 
751
#endif
 
752