+ /Views/Default/Index.html
+ ~/Index.html
+
+
+ ../Index.html
+ http://www.contoso.com/
+ http://localhost/Index.html
+
+ ^[A-Za-z]*$
+ ○ Match if at the beginning of the string.
+ ○ Match a character in the set [A-Za-z] atomically any number of times.
+ ○ Match if at the end of the string or if before an ending newline.
+
+
+ Route Template: "{controller=Home}/{action=Index}/{id?}"
+ Route Values: { controller = "Store", action = "Index" }
+
+
+ A route pattern produced in this way will match and generate URL paths like: array
at which copying begins.
+ true
if the false
.true
if access to the false
.true
if the false
.true
if the false
.null
if the key does not exist.true
if the enumerator was successfully advanced to the next element; false
if the enumerator has passed the end of the collection.true
if the current set is a proper subset of other
; otherwise, false
.true
if the current set is a proper superset of other
; otherwise, false
.true
if the current set is a subset of other
; otherwise, false
.true
if the current set is a superset of other
; otherwise, false
.true
if the current set and other
share at least one common element; otherwise, false
.true
if the current set is equal to other
; otherwise, false
.array
at which copying begins.
+ true
if access to the false
.true
if the enumerator was successfully advanced to the next element; false
if the enumerator has passed the end of the collection.source
to destination
, reversing each primitive by performing an endianness swap as part of writing each.source
to destination
, reversing each primitive by performing an endianness swap as part of writing each.source
to destination
, reversing each primitive by performing an endianness swap as part of writing each.source
to destination
, reversing each primitive by performing an endianness swap as part of writing each.source
to destination
, reversing each primitive by performing an endianness swap as part of writing each.source
to destination
, reversing each primitive by performing an endianness swap as part of writing each.source
to destination
, reversing each primitive by performing an endianness swap as part of writing each.source
to destination
, reversing each primitive by performing an endianness swap as part of writing each.source
to destination
, reversing each primitive by performing an endianness swap as part of writing each.true
if found, false
otherwise.value0
or value1
, and returns true
if found. If not found, returns false
.value0
, value1
, or value2
, and returns true
if found. If not found, returns false
.values
and returns true
if found. If not found, returns false
.values
and returns true
if found. If not found, returns false
.value
.true
if any value other than value
is present in the span.
+If all of the values are value
, returns false
.value0
or value1
.true
if any value other than value0
or value1
is present in the span.
+If all of the values are value0
or value1
, returns false
.value0
, value1
, or value2
.true
if any value other than value0
, value1
, or value2
is present in the span.
+If all of the values are value0
, value1
, or value2
, returns false
.values
.true
if any value other than those in values
is present in the span.
+If all of the values are in values
, returns false
.values
.true
if any value other than those in values
is present in the span.
+If all of the values are in values
, returns false
.lowInclusive
and highInclusive
, inclusive.true
if any value other than those in the specified range is present in the span.
+If all of the values are inside of the specified range, returns false
.lowInclusive
and highInclusive
, inclusive, and returns true
if found. If not found, returns false
.lowInclusive
and highInclusive
, inclusive.lowInclusive
and highInclusive
, inclusive.lowInclusive
and highInclusive
, inclusive.lowInclusive
and highInclusive
, inclusive.null
.
+ An object that defines a set of properties and enables binding, which can involve selection of an overloaded method, coercion of argument types, and invocation of a member through reflection.
+
+ -or-
+
+ A null reference (Nothing
in Visual Basic), to use the types
array. The default binder does not process this parameter.
+ null
.null
.
+ An object that defines a set of properties and enables binding, which can involve selection of an overloaded method, coercion of argument types, and invocation of a member through reflection.
+
+ -or-
+
+ A null reference (Nothing
in Visual Basic), to use the null
. If types
is null
, arguments are not matched.
+ An array of types
array. The default binder does not process this parameter.
+ null
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the current false
.true
if the current false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the current false
.true
if the current false
.null
.
+ An object that defines a set of properties and enables binding, which can involve selection of an overloaded method, coercion of argument types, and invocation of a member through reflection.
+
+ -or-
+
+ A null reference (Nothing
in Visual Basic), to use the types
array. The default binder does not process this parameter.
+ null
.null
.
+ An object that defines a set of properties and enables binding, which can involve selection of an overloaded method, coercion of argument types, and invocation of a member through reflection.
+
+ -or-
+
+ A null reference (Nothing
in Visual Basic), to use the null
. If types
is null
, arguments are not matched.
+ An array of types
array. The default binder does not process this parameter.
+ null
.null
.
+ An object that defines a set of properties and enables binding, which can involve selection of an overloaded member, coercion of argument types, and invocation of a member through reflection.
+
+ -or-
+
+ A null reference (Nothing
in Visual Basic), to use the types
array. The default binder does not process this parameter.
+ null
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
if the false
.true
to recursively clone the subtree under the specified node; false
to clone only the node itself.
+ XmlWriter
to which you want to save.
+ XmlWriter
to which you want to save.
+ XmlProcessingInstruction
nodes, this value is XmlNodeType.ProcessingInstruction.
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample.Values // evaluates to seq ["a"; "b"]
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample.Keys // evaluates to seq [1; 2]
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample.[1] // evaluates to "a"
+ sample.[3] // throws KeyNotFoundException
+
+
+ let emptyMap: Map<int, string> = Map.empty
+ emptyMap.IsEmpty // evaluates to true
+
+ let notEmptyMap = Map [ (1, "a"); (2, "b") ]
+ notEmptyMap.IsEmpty // evaluates to false
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample.Count // evaluates to 2
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample.TryGetValue 1 // evaluates to (true, "a")
+ sample.TryGetValue 3 // evaluates to (false, null)
+
+ let mutable x = ""
+ sample.TryGetValue (1, &x) // evaluates to true, x set to "a"
+
+ let mutable y = ""
+ sample.TryGetValue (3, &y) // evaluates to false, y unchanged
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample.TryFind 1 // evaluates to Some "a"
+ sample.TryFind 3 // evaluates to None
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample.Remove 1 // evaluates to map [(2, "b")]
+ sample.Remove 3 // equal to sample
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample.ContainsKey 1 // evaluates to true
+ sample.ContainsKey 3 // evaluates to false
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ let f x =
+ match x with
+ | Some s -> Some (s + "z")
+ | None -> None
+
+ sample.Change (1, f) // evaluates to map [(1, "az"); (2, "b")]
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample.Add (3, "c") // evaluates to map [(1, "a"); (2, "b"); (3, "c")]
+ sample.Add (2, "aa") // evaluates to map [(1, "a"); (2, "aa")]
+
+
+ Map [ (1, "a"); (2, "b") ] // evaluates to map [(1, "a"); (2, "b")]
+
+
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(2).Add(3).Add(4)
+ printfn $"The new set is: {set1 - set2}"
+
+ The sample evaluates to the following output:
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(2).Add(3).Add(4)
+ printfn $"Output is %A" {set1 + set2}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ printfn $"MinimumElement: {set.MinimumElement}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ printfn $"MaximumElement: {set.MaximumElement}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(2).Add(3)
+ printfn $"Is the set empty? {set.IsEmpty}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(1).Add(2)
+ printfn $"The set has {set.Count} elements"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(1).Add(2)
+ printfn $"The new set is: {set}"
+
+ The sample evaluates to the following output:
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(1).Add(2).Add(3).Add(4)
+ printfn $"Is {set1} a superset of {set2}? {Set.isSuperset set1 set2}"
+
+ The sample evaluates to the following output:
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(1).Add(2).Add(3).Add(4)
+ printfn $"Is {set1} a subset of {set2}? {Set.isSubset set1 set2}"
+
+ The sample evaluates to the following output:
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(1).Add(2).Add(3).Add(4)
+ printfn $"Is {set1} a proper superset of {set2}? {Set.isProperSuperset set1 set2}"
+
+ The sample evaluates to the following output:
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(1).Add(2).Add(3).Add(4)
+ printfn $"Is {set1} a proper superset of {set2}? {Set.isProperSuperset set1 set2}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(2).Add(3)
+ printfn $"Does the set contain 1? {set.Contains(1)}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(1).Add(2)
+ printfn $"The new set is: {set}"
+
+ The sample evaluates to the following output:
+ let sequenceOfNumbers = seq { 1 .. 3 }
+ let numbersInSet = Set(sequenceOfNumbers)
+ printfn $"The set is {numbersInSet}"
+
+
+ let array = array2D [ [ 1.0; 2.0 ]; [ 3.0; 4.0 ] ]
+
+ array[0,1]
+
+ Evaluates to
+ let array = array2D [ [ 1.0; 2.0 ]; [ 3.0; 4.0 ] ]
+
+ Array2D.get array 0 1
+
+ Evaluates to
+ let array = Array2D.zeroCreate 2 2
+
+ array[0,1] <- 4.0
+
+
+ let array = Array2D.zeroCreate 2 2
+
+ Array2D.set array 0 1 4.0
+
+ After evaluation
+ let inputs = Array2D.createBased 1 1 2 3 1
+
+ inputs |> Array2D.rebase
+
+ Evaluates to a 2x2 zero-based array with contents
+ let inputs = array2D [ [ 3; 4 ]; [ 13; 14 ] ]
+
+ inputs |> Array2D.mapi (fun i j v -> i + j + v)
+
+ Evaluates to a 2x2 array with contents
+ let inputs = array2D [ [ 3; 4 ]; [ 13; 14 ] ]
+
+ inputs |> Array2D.map (fun v -> 2 * v)
+
+ Evaluates to a 2x2 array with contents
+ let array = array2D [ [ 3; 4; 5 ]; [ 13; 14; 15 ] ]
+
+ array |> Array2D.length2
+
+ Evaluates to
+ let array = array2D [ [ 3; 4; 5 ]; [ 13; 14; 15 ] ]
+
+ array |> Array2D.length1
+
+ Evaluates to
+ let inputs = array2D [ [ 3; 4 ]; [ 13; 14 ] ]
+
+ inputs |> Array2D.iteri (fun i j v -> printfn $"value at ({i},{j}) = {v}")
+
+ Evaluates to
+ value at (0,0) = 3
+ value at (0,1) = 4
+ value at (1,0) = 13
+ value at (1,1) = 14
+
+ in the console.
+
+ let inputs = array2D [ [ 3; 4 ]; [ 13; 14 ] ]
+
+ inputs |> Array2D.iter (fun v -> printfn $"value = {v}")
+
+ Evaluates to
+ value = 3
+ value = 4
+ value = 13
+ value = 14
+
+ in the console.
+
+ Array2D.zeroCreateBased 1 1 2 3
+
+ Evaluates to a 2x3 1-based array with contents
+ Array2D.createBased 1 1 2 3 1
+
+ Evaluates to a 2x3 1-based array with contents
+ Array2D.initBased 1 1 2 3 (fun i j -> i + j)
+
+ Evaluates to a 2x3 1-based array with contents
+ Array2D.zeroCreate 2 3
+
+ Evaluates to a 2x3 array with contents
+ Array2D.create 2 3 1
+
+ Evaluates to a 2x3 array with contents
+ Array2D.init 2 3 (fun i j -> i + j)
+
+ Evaluates to a 2x3 array with contents
+ let source = array2D [ [ 3; 4 ]; [ 13; 14 ] ]
+ let target = array2D [ [ 2; 2; 2 ]; [ 12; 12; 12 ] ]
+ target[0..1,1..2] <- source
+
+
+ let source = array2D [ [ 3; 4 ]; [ 13; 14 ] ]
+ let target = array2D [ [ 2; 2; 2 ]; [ 12; 12; 12 ] ]
+
+ Array2D.blit source 0 0 target 0 1 2 2
+
+ After evaluation
+ open System
+
+ let array = Array2D.zeroCreate<int> 10 10
+
+ array |> Array2D.copy
+
+ Evaluates to a new copy of the 10x10 array.
+
+ open System
+
+ let array = Array.CreateInstance(typeof<int>, [| 10; 10 |], [| 1; 1 |]) :?> int[,]
+
+ array |> Array2D.base2
+
+ Evaluates to
+ open System
+
+ let array = Array.CreateInstance(typeof<int>, [| 10; 10 |], [| 1; 1 |]) :?> int[,]
+
+ array |> Array2D.base1
+
+ Evaluates to
+ open System.Collections.Generic
+
+ let modIdentity = HashIdentity.FromFunctions((fun i -> i%5), (fun i1 i2 -> i1%5 = i2%5))
+ let dict = new Dictionary<int,int>(HashIdentity.FromFunctions)
+
+ dict.[2] <- 6
+ dict.[7] <- 10
+
+ In this example, only one entry is added, as the keys
+ open System.Collections.Generic
+
+ let dict = new Dictionary<int array,int>(HashIdentity.Structural)
+
+ let arr1 = [| 1;2;3 |]
+ let arr2 = [| 1;2;3 |]
+ dict.Add(arr1, 6)
+ dict.Add(arr2, 7)
+
+ In this example, two entries are added to the dictionary, as the arrays have different object reference identity.
+
+ open System.Collections.Generic
+
+ type Tree = Tree of int * Tree list
+
+ let dict = new Dictionary<Tree,int>(HashIdentity.LimitedStructural 4)
+
+ let tree1 = Tree(0, [])
+ let tree2 = Tree(0, [tree1; tree1])
+ dict.Add(tree1, 6)
+ dict.Add(tree2, 7)
+
+
+ open System.Collections.Generic
+
+ let dict = new Dictionary<System.DateTime,int>(HashIdentity.NonStructural)
+
+ dict.Add(System.DateTime.Now, 1)
+
+
+ open System.Collections.Generic
+
+ let dict = new Dictionary<int array,int>(HashIdentity.Structural)
+
+ let arr1 = [| 1;2;3 |]
+ let arr2 = [| 1;2;3 |]
+
+ dict.[arr1] <- 6
+ dict.[arr2] >- 7
+
+ In this example, only one entry is added to the dictionary, as the arrays identical by structural equality.
+
+ let comparer = ComparisonIdentity.FromFunction(fun i1 i2 -> compare (i1%5) (i2%5))
+
+ comparer.Compare(7, 2)
+
+ Evaluates to
+ let comparer = ComparisonIdentity.NonStructural<System.DateTime>
+
+ comparer.Compare(System.DateTime.Now, System.DateTime.Today)
+
+ Evaluates to
+ let compareTuples = ComparisonIdentity.Structural<int * int>
+
+ compareTuples.Compare((1, 4), (1, 5))
+
+ Evaluates to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+
+ inputs |> Seq.randomSampleBy Random.Shared.NextDouble 3
+
+ Can evaluate to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+
+ inputs |> Seq.randomSampleWith Random.Shared 3
+
+ Can evaluate to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+
+ inputs |> Seq.randomSample 3
+
+ Can evaluate to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+
+ inputs |> Seq.randomChoicesBy Random.Shared.NextDouble 3
+
+ Can evaluate to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+
+ inputs |> Seq.randomChoicesWith Random.Shared 3
+
+ Can evaluate to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+
+ inputs |> Seq.randomChoices 3
+
+ Can evaluate to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+ let randomizer = Random.Shared.NextDouble
+
+ inputs |> Seq.randomChoiceBy randomizer
+
+ Can evaluate to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+
+ inputs |> Seq.randomChoiceWith Random.Shared
+
+ Can evaluate to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+
+ inputs |> Seq.randomChoice
+
+ Can evaluate to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+
+ inputs |> Seq.randomShuffleBy Random.Shared.NextDouble
+
+ Can evaluate to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+
+ inputs |> Seq.randomShuffleWith Random.Shared
+
+ Can evaluate to
+ let inputs = seq { 0; 1; 2; 3; 4 }
+
+ inputs |> Seq.randomShuffle
+
+ Can evaluate to
+ seq { 0; 1; 2 } |> Seq.insertManyAt 1 [8; 9]
+
+ Evaluates to a sequence yielding the same results as
+ seq { 0; 1; 2 } |> Seq.insertAt 1 9
+
+ Evaluates to a sequence yielding the same results as
+ seq { 0; 1; 2 } |> Seq.updateAt 1 9
+
+ Evaluates to a sequence yielding the same results as
+ seq { 0; 1; 2; 3 } |> Seq.removeManyAt 1 2
+
+ Evaluates to a sequence yielding the same results as
+ seq { 0; 1; 2 } |> Seq.removeAt 1
+
+ Evaluates to a sequence yielding the same results as
+ let numbers = [1; 2]
+ let names = ["one"; "two"]
+ let roman = ["I"; "II"]
+
+ Seq.zip3 numbers names roman
+
+ Evaluates to a sequence yielding the same results as
+ let numbers = [1; 2]
+ let names = ["one"; "two"]
+
+ Seq.zip numbers names
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> Seq.windowed 3
+
+ Evaluates to a sequence of arrays yielding the results
+ 1 |> Seq.unfold (fun state -> if state > 100 then None else Some (state, state * 2))
+
+ Evaluates to a sequence yielding the same results as
+ 1I |> Seq.unfold (fun state -> Some (state, state * 2I))
+
+ Evaluates to an infinite sequence yielding the results
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> Seq.truncate 2
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> Seq.truncate 6
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> Seq.truncate 0
+
+ Evaluates to the empty sequence.
+
+ let inputs =
+ [ [ 10; 20; 30 ]
+ [ 11; 21; 31 ] ]
+
+ inputs |> Seq.transpose
+
+ Evaluates to a sequence of sequences yielding the same results as
+ let input = [1; 2; 3]
+
+ input |> Seq.tryPick (fun n -> if n % 2 = 0 then Some (string n) else None)
+
+ Evaluates to
+ let input = [1; 2; 3]
+
+ input |> Seq.tryPick (fun n -> if n > 3 = 0 then Some (string n) else None)
+
+ Evaluates to
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> Seq.tryFindIndexBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 3; 5; 7]
+
+ inputs |> Seq.tryFindIndexBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"]
+
+ inputs |> Seq.tryItem 1
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"]
+
+ inputs |> Seq.tryItem 4
+
+ Evaluates to
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> Seq.tryFindIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 3; 5; 7]
+
+ inputs |> Seq.tryFindIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> Seq.tryFindBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 5; 3]
+
+ inputs |> Seq.tryFindBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 2; 3]
+
+ inputs |> Seq.tryFind (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 5; 3]
+
+ inputs |> Seq.tryFind (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = seq { 1; 2; 5 }
+
+ inputs |> Seq.toList
+
+ Evaluates to
+ let inputs = seq { 1; 2; 5 }
+
+ inputs |> Seq.toArray
+
+ Evaluates to
+ let inputs = ["a"; "bb"; "ccc"; "d"]
+
+ inputs |> Seq.takeWhile (fun x -> x.Length < 3)
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> Seq.take 2
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> Seq.take 6
+
+ Throws
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> Seq.take 0
+
+ Evaluates to a sequence yielding no results.
+
+ let inputs = ["a"; "bb"; "ccc"]
+
+ inputs |> Seq.tail
+
+ Evaluates to a sequence yielding the same results as
+ let input = [ "aa"; "bbb"; "cc" ]
+
+ input |> Seq.sumBy (fun s -> s.Length)
+
+ Evaluates to
+ let input = [ 1; 5; 3; 2 ]
+
+ input |> Seq.sum
+
+ Evaluates to
+ let input = ["a"; "bbb"; "cccc"; "dd"]
+
+ input |> Seq.sortByDescending (fun s -> s.Length)
+
+ Evaluates to a sequence yielding the same results as
+ let input = seq { 8; 4; 3; 1; 6; 1 }
+
+ input |> Seq.sortDescending
+
+ Evaluates to a sequence yielding the same results as
+ let input = [ "a"; "bbb"; "cccc"; "dd" ]
+
+ input |> Seq.sortBy (fun s -> s.Length)
+
+ Evaluates to a sequence yielding the same results as
+ let compareEntries (n1: int, s1: string) (n2: int, s2: string) =
+ let c = compare s1.Length s2.Length
+ if c <> 0 then c else
+ compare n1 n2
+
+ let input = [ (0,"aa"); (1,"bbb"); (2,"cc"); (3,"dd") ]
+
+ input |> Seq.sortWith compareEntries
+
+ Evaluates to a sequence yielding the same results as
+ let input = seq { 8; 4; 3; 1; 6; 1 }
+
+ Seq.sort input
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = seq { "a"; "bbb"; "cc"; "d" }
+
+ inputs |> Seq.skipWhile (fun x -> x.Length < 3)
+
+ Evaluates a sequence yielding the same results as
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> Seq.skip 2
+
+ Evaluates a sequence yielding the same results as
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> Seq.skip 5
+
+ Throws
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> Seq.skip -1
+
+ Evaluates a sequence yielding the same results as
+ Seq.singleton 7
+
+ Evaluates to a sequence yielding the same results as
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = [ In 1; Out 2; In 3 ]
+
+ (inputs, 0) ||> Seq.scanBack (fun charge acc ->
+ match charge with
+ | In i -> acc + i
+ | Out o -> acc - o)
+
+ Evaluates to a sequence yielding the same results as
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = seq { In 1; Out 2; In 3 }
+
+ (0, inputs) ||> Seq.scan (fun acc charge ->
+ match charge with
+ | In i -> acc + i
+ | Out o -> acc - o)
+
+ Evaluates to a sequence yielding the same results as
+ let input = seq { 0; 1; 2 }
+
+ input |> Seq.rev
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = [1; 3; 4; 2]
+
+ inputs |> Seq.reduceBack (fun a b -> a + b * 10)
+
+ Evaluates to
+ Seq.replicate 3 "a"
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = [1; 3; 4; 2]
+
+ inputs |> Seq.reduce (fun a b -> a * 10 + b)
+
+ Evaluates to
+ let input = [| 1; 2; 3 |]
+
+ input |> Seq.readonly
+
+ Evaluates to a sequence yielding the same results as
+ let input = [| 1; 2; 3 |]
+
+ let readonlyView = input |> Seq.readonly
+
+ (readonlyView :?> int array).[1] <- 4
+
+ Throws an
+ let input = [1; 2; 3]
+
+ input |> Seq.pick (fun n -> if n % 2 = 0 then Some (string n) else None)
+
+ Evaluates to
+ let input = [1; 2; 3]
+
+ input |> Seq.pick (fun n -> if n > 3 = 0 then Some (string n) else None)
+
+ Throws
+ let inputs = [1; 2; 3; 4]
+
+ inputs |> Seq.permute (fun x -> (x + 1) % 4)
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = seq { 1; 2; 3; 4 }
+
+ inputs |> Seq.pairwise
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = [ 1; 2; 5 ]
+
+ inputs |> Seq.ofList
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = [| 1; 2; 5 |]
+
+ inputs |> Seq.ofArray
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = [ "aaa"; "b"; "cccc" ]
+
+ inputs |> Seq.minBy (fun s -> s.Length)
+
+ Evaluates to
+ let inputs = []
+
+ inputs |> Seq.minBy (fun (s: string) -> s.Length)
+
+ Throws
+ let inputs = [10; 12; 11]
+
+ inputs |> Seq.min
+
+ Evaluates to
+ let inputs = []
+
+ inputs |> Seq.min
+
+ Throws
+ let inputs = ["aaa"; "b"; "cccc"]
+
+ inputs |> Seq.maxBy (fun s -> s.Length)
+
+ Evaluates to
+ let inputs = [ ]
+
+ inputs |> Seq.maxBy (fun s -> s.Length)
+
+ Throws
+ let inputs = [ 10; 12; 11 ]
+
+ inputs |> Seq.max
+
+ Evaluates to
+ let inputs = [ ]
+
+ inputs |> Seq.max
+
+ Throws
+ let inputs1 = ["a"; "bad"; "good"]
+ let inputs2 = [0; 2; 1]
+
+ (inputs1, inputs2) ||> Seq.mapi2 (fun i x y -> i, x[y])
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = [ 10; 10; 10 ]
+
+ inputs |> Seq.mapi (fun i x -> i + x)
+
+ Evaluates to a sequence yielding the same results as
+ let inputs1 = [ "a"; "t"; "ti" ]
+ let inputs2 = [ "l"; "h"; "m" ]
+ let inputs3 = [ "l"; "e"; "e" ]
+
+ (inputs1, inputs2, inputs3) |||> Seq.map3 (fun x y z -> x + y + z)
+
+ Evaluates to a sequence yielding the same results as
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = seq { In 1; Out 2; In 3 }
+
+ let newCharges, balance =
+ (inputs, 0) ||> Seq.mapFoldBack (fun charge acc ->
+ match charge with
+ | In i -> In (i*2), acc + i
+ | Out o -> Out (o*2), acc - o)
+
+ Evaluates Accumulate the charges, and double them as well
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = seq { In 1; Out 2; In 3 }
+
+ let newCharges, balance =
+ (0, inputs) ||> Seq.mapFold (fun acc charge ->
+ match charge with
+ | In i -> In (i*2), acc + i
+ | Out o -> Out (o*2), acc - o)
+
+ Evaluates
+ let inputs1 = ["a"; "bad"; "good"]
+ let inputs2 = [0; 2; 1]
+
+ (inputs1, inputs2) ||> Seq.map2 (fun x y -> x.[y])
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = ["a"; "bbb"; "cc"]
+
+ inputs |> Seq.map (fun x -> x.Length)
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = ["a"; "b"; "c"]
+
+ inputs |> Seq.length
+
+ Evaluates to
+ let inputs1 = ["a"; "b"; "c"]
+ let inputs2 = ["banana"; "pear"; "apple"]
+
+ (inputs1, inputs2) ||> Seq.iteri2 (fun i s1 s2 -> printfn "Index {i}: {s1} - {s2}")
+
+ Evaluates to
+ Index 0: a - banana
+ Index 1: b - pear
+ Index 2: c - apple
+
+ in the console.
+
+ let inputs1 = ["a"; "b"; "c"]
+ let inputs2 = [1; 2; 3]
+
+ (inputs1, inputs2) ||> Seq.iter2 (printfn "%s: %i")
+
+ Evaluates to
+ a: 1
+ b: 2
+ c: 3
+
+ in the console.
+
+ let inputs = ["a"; "b"; "c"]
+
+ inputs |> Seq.iteri (fun i v -> printfn "{i}: {v}")
+
+
+ Evaluates to
+ 0: a
+ 1: b
+ 2: c
+
+ in the console.
+
+ ["a"; "b"; "c"] |> Seq.iter (printfn "%s")
+
+ Evaluates to
+ a
+ b
+ c
+
+ in the console.
+
+ let inputs = ["a"; "b"; "c"]
+
+ inputs |> Seq.item 1
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"]
+
+ inputs |> Seq.item 4
+
+ Throws
+ (+) 5 |> Seq.initInfinite
+
+ Evaluates to a sequence yielding the same results as
+ Seq.init 4 (fun v -> v + 5)
+
+ Evaluates to a sequence yielding the same results as
+ Seq.init -5 (fun v -> v + 5)
+
+ Throws
+ ["a"; "b"; "c"] |> Seq.indexed
+
+ Evaluates to a sequence yielding the same results as
+ [] |> Seq.isEmpty
+
+ Evaluates to
+ ["pear"; "banana"] |> Seq.isEmpty
+
+ Evaluates to
+ let inputs = ["banana"]
+
+ inputs |> Seq.tryExactlyOne
+
+ Evaluates to
+ let inputs = ["pear"; "banana"]
+
+ inputs |> Seq.tryExactlyOne
+
+ Evaluates to
+ [] |> Seq.tryExactlyOne
+
+ Evaluates to
+ let inputs = ["banana"]
+
+ inputs |> Seq.exactlyOne
+
+ Evaluates to
+ let inputs = ["pear"; "banana"]
+
+ inputs |> Seq.exactlyOne
+
+ Throws
+ [] |> Seq.exactlyOne
+
+ Throws
+ ["pear"; "banana"] |> Seq.tryLast
+
+ Evaluates to
+ [] |> Seq.tryLast
+
+ Evaluates to
+ ["pear"; "banana"] |> Seq.last
+
+ Evaluates to
+ [] |> Seq.last
+
+ Throws
+ ["banana"; "pear"] |> Seq.tryHead
+
+ Evaluates to
+ [] |> Seq.tryHead
+
+ Evaluates to
+ let inputs = ["banana"; "pear"]
+
+ inputs |> Seq.head
+
+ Evaluates to
+ [] |> Seq.head
+
+ Throws
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> Seq.groupBy (fun n -> n % 2)
+
+ Evaluates to a sequence yielding the same results as
+ let inputs1 = [1; 2; 3; 4; 5; 6]
+ let inputs2 = [1; 2; 3; 4; 5]
+
+ (inputs1, inputs2) ||> Seq.forall2 (=)
+
+ Evaluates to
+ let items1 = [2017; 1; 1]
+ let items2 = [2019; 19; 8]
+
+ (items1, items2) ||> Seq.forall2 (=)
+
+ Evaluates to
+ let isEven a = a % 2 = 0
+
+ [2; 42] |> Seq.forall isEven // evaluates to true
+
+ [1; 2] |> Seq.forall isEven // evaluates to false
+
+
+ type Count =
+ { Positive: int
+ Negative: int
+ Text: string }
+
+ let inputs1 = [-1; -2; -3]
+ let inputs2 = [3; 2; 1; 0]
+ let initialState = {Positive = 0; Negative = 0; Text = ""}
+
+ (inputs1, inputs2, initialState) |||> Seq.foldBack2 (fun a b acc ->
+ let text = acc.Text + "(" + string a + "," + string b + ") "
+ if a + b >= 0 then
+ { acc with
+ Positive = acc.Positive + 1
+ Text = text }
+ else
+ { acc with
+ Negative = acc.Negative + 1
+ Text = text }
+ )
+
+ Evaluates to
+
+ { Positive = 2
+ Negative = 1
+ Text = " (-3,1) (-2,2) (-1,3)" }
+
+
+ type Count =
+ { Positive: int
+ Negative: int
+ Text: string }
+
+ let sequence = [1; 0; -1; -2; 3]
+ let initialState = {Positive = 0; Negative = 0; Text = ""}
+
+ (sequence, initialState) ||> Seq.foldBack (fun a acc ->
+ let text = acc.Text + " " + string a
+ if a >= 0 then
+ { acc with
+ Positive = acc.Positive + 1
+ Text = text }
+ else
+ { acc with
+ Negative = acc.Negative + 1
+ Text = text })
+
+ Evaluates to
+
+ { Positive = 2
+ Negative = 3
+ Text = " 3 -2 -1 0 1" }
+
+
+ type CoinToss = Head | Tails
+
+ let data1 = [Tails; Head; Tails]
+ let data2 = [Tails; Head; Head]
+
+ (0, data1, data2) |||> Seq.fold2 (fun acc a b ->
+ match (a, b) with
+ | Head, Head -> acc + 1
+ | Tails, Tails -> acc + 1
+ | _ -> acc - 1)
+
+ Evaluates to
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = [In 1; Out 2; In 3]
+
+ (0, inputs) ||> Seq.fold (fun acc charge ->
+ match charge with
+ | In i -> acc + i
+ | Out o -> acc - o)
+
+ Evaluates to
+ let input = [1; 2; 3; 4; 5]
+
+ input |> Seq.findIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let input = [1; 2; 3; 4; 5]
+
+ input |> Seq.findIndex (fun elm -> elm % 6 = 0)
+
+ Throws
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> Seq.findIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 2; 3; 4; 5]
+ inputs |> Seq.findIndex (fun elm -> elm % 6 = 0)
+
+ Throws
+ let inputs = [2; 3; 4]
+
+ inputs |> Seq.findBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [2; 3; 4]
+
+ inputs |> Seq.findBack (fun elm -> elm % 6 = 0)
+
+ Throws
+ let inputs = [1; 2; 3]
+
+ inputs |> Seq.find (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 2; 3]
+
+ inputs |> Seq.find (fun elm -> elm % 6 = 0)
+
+ Throws
+ [1; 2; 3; 4] |> Seq.where (fun elm -> elm % 2 = 0)
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = [1; 2; 3; 4]
+
+ inputs |> Seq.filter (fun elm -> elm % 2 = 0)
+
+ Evaluates to a sequence yielding the same results as
+ let inputs1 = [1; 2]
+ let inputs2 = [1; 2; 0]
+
+ (inputs1, inputs2) ||> Seq.exists2 (fun a b -> a > b)
+
+ Evaluates to
+ let inputs1 = [1; 4]
+ let inputs2 = [1; 3; 5]
+
+ (inputs1, inputs2) ||> Seq.exists2 (fun a b -> a > b)
+
+ Evaluates to
+ let input = [1; 2; 3; 4; 5]
+
+ input |> Seq.exists (fun elm -> elm % 4 = 0)
+
+ Evaluates to
+ let input = [1; 2; 3; 4; 5]
+
+ input |> Seq.exists (fun elm -> elm % 6 = 0)
+
+ Evaluates to
+ let original = [1; 2; 3; 4; 5]
+ let itemsToExclude = [1; 3; 5]
+
+ original |> Seq.except itemsToExclude
+
+ Evaluates to a sequence yielding the same results as
+ Seq.empty // Evaluates to seq { }
+
+
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> Seq.splitInto 3
+
+ Evaluates to a sequence yielding the same results as
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> Seq.splitInto -1
+
+ Throws
+ let inputs = [{Bar = 1 };{Bar = 1}; {Bar = 2}; {Bar = 3}]
+
+ inputs |> Seq.distinctBy (fun foo -> foo.Bar)
+
+ Evaluates to a sequence yielding the same results as
+ [1; 1; 2; 3] |> Seq.distinct
+
+ Evaluates to a sequence yielding the same results as
+ Seq.delay (fun () -> Seq.ofList [1; 2; 3])
+
+ Evaluates to a sequence yielding the same results as
+ type Foo = { Bar: string }
+
+ let inputs = [{Bar = "a"}; {Bar = "b"}; {Bar = "a"}]
+
+ inputs |> Seq.countBy (fun foo -> foo.Bar)
+
+ Evaluates to a sequence yielding the same results as
+ [1; 2] |> Seq.contains 2 // evaluates to true
+ [1; 2] |> Seq.contains 5 // evaluates to false
+
+
+ let inputs = [[1; 2]; [3]; [4; 5]]
+
+ inputs |> Seq.concat
+
+ Evaluates to a sequence yielding the same results as
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [1; 10]
+ let input2 = [1; 10]
+
+ (input1, input2) ||> Seq.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [1; 5]
+ let input2 = [1; 8]
+
+ (input1, input2) ||> Seq.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [1; 11]
+ let input2 = [1; 13]
+
+ (input1, input2) ||> Seq.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [1; 2]
+ let input2 = [1]
+
+ (input1, input2) ||> Seq.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [1]
+ let input2 = [1; 2]
+
+ (input1, input2) ||> Seq.compareWith closerToNextDozen
+
+ Evaluates to
+ type Foo = { Bar: int seq }
+
+ let input = seq { {Bar = [1; 2]}; {Bar = [3; 4]} }
+
+ input |> Seq.collect (fun foo -> foo.Bar)
+
+ Evaluates to a sequence yielding the same results as
+ let input = [[1; 2]; [3; 4]]
+
+ input |> Seq.collect id
+
+ Evaluates to a sequence yielding the same results as
+ [1; 2; 3] |> Seq.chunkBySize 2
+
+ Evaluates to a sequence yielding the same results as
+ [1; 2; 3] |> Seq.chunkBySize -2
+
+ Throws
+ [Some 1; None; Some 2] |> Seq.choose id
+
+ Evaluates to a sequence yielding the same results as
+ [1; 2; 3] |> Seq.choose (fun n -> if n % 2 = 0 then Some n else None)
+
+ Evaluates to a sequence yielding the same results as
+ [box 1; box 2; box 3] |> Seq.cast<int>
+
+ Evaluates to a sequence yielding the same results as
+ let fibSeq =(0, 1) |> Seq.unfold (fun (a,b) -> Some(a + b, (b, a + b)))
+
+ let fibSeq3 = fibSeq |> Seq.take 3 |> Seq.cache
+ fibSeq3
+
+ Evaluates to a sequence yielding the same results as
+ type Foo = { Bar: float }
+
+ let input = seq { {Bar = 2.0}; {Bar = 4.0} }
+
+ input |> Seq.averageBy (fun foo -> foo.Bar)
+
+ Evaluates to
+ type Foo = { Bar: float }
+
+ Seq.empty |> Seq.averageBy (fun (foo: Foo) -> foo.Bar)
+
+ Throws
+ [1.0; 2.0; 3.0] |> Seq.average
+
+ Evaluates to
+ [] |> Seq.average
+
+ Throws
+ Seq.append [1; 2] [3; 4]
+
+ Evaluates to a sequence yielding the same results as
+ ([1; 2], [3; 4]) ||> Seq.allPairs
+
+ Evaluates to a sequence yielding the same results as
+
+ seq { (1, 3); (1, 4); (2, 3); (2, 4) }
+
+
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> List.randomSampleBy Random.Shared.NextDouble 3
+
+ Can evaluate to
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> List.randomSampleWith Random.Shared 3
+
+ Can evaluate to
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> List.randomSample 3
+
+ Can evaluate to
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> List.randomChoicesBy Random.Shared.NextDouble 3
+
+ Can evaluate to
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> Array.randomChoicesWith Random.Shared 3
+
+ Can evaluate to
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> List.randomChoices 3
+
+ Can evaluate to
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> List.randomChoiceBy Random.Shared.NextDouble
+
+ Can evaluate to
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> List.randomChoiceWith Random.Shared
+
+ Can evaluate to
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> List.randomChoice
+
+ Can evaluate to
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> List.randomShuffleBy Random.Shared.NextDouble
+
+ Can evaluate to
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> List.randomShuffleWith Random.Shared
+
+ Can evaluate to
+ let inputs = [ 0; 1; 2; 3; 4 ]
+
+ inputs |> List.randomShuffle
+ Can evaluate to [ 0; 2; 4; 3; 1 ] .
+
+
+ let inputs = [ 0; 1; 2 ]
+
+ inputs |> List.insertManyAt 1 [ 8; 9 ]
+ Evaluates to [ 0; 8; 9; 1; 2 ] .
+
+
+ let inputs = [ 0; 1; 2 ]
+
+ inputs |> List.insertAt 1 9
+
+ Evaluates to
+ let inputs = [ 0; 1; 2 ]
+
+ inputs |> List.updateAt 1 9
+
+ Evaluates to
+ let inputs = [ 0; 1; 2; 3 ]
+
+ inputs |> List.removeManyAt 1 2
+
+ Evaluates to
+ let inputs = [ 0; 1; 2 ]
+
+ inputs |> List.removeAt 1
+
+ let inputs = [ 0; 2 ]
+
+ let numbers = [1; 2]
+ let names = ["one"; "two"]
+ let roman = ["I"; "II"]
+
+ List.zip3 numbers names roman
+
+ Evaluates to
+ let numbers = [1; 2]
+ let names = ["one"; "two"]
+
+ List.zip numbers names
+
+ Evaluates to
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> List.windowed 3
+
+ Evaluates to
+ let inputs = [1; 2; 3; 4]
+
+ inputs |> List.where (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [(1, "one", "I"); (2, "two", "II")]
+
+ let numbers, names, roman = inputs |> List.unzip3
+
+ Evaluates
+ let inputs = [(1, "one"); (2, "two")]
+
+ let numbers, names = inputs |> List.unzip
+
+ Evaluates
+ 1 |> List.unfold (fun state -> if state > 100 then None else Some (state, state * 2))
+
+ Evaluates to
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> List.tryFindIndexBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 3; 5; 7]
+
+ inputs |> List.tryFindIndexBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"]
+
+ inputs |> List.tryItem 1
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"]
+
+ inputs |> List.tryItem 4
+
+ Evaluates to
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> List.tryFindIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 3; 5; 7]
+
+ inputs |> List.tryFindIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> List.tryFindBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 5; 3]
+
+ inputs |> List.tryFindBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 2; 3]
+
+ inputs |> List.tryFind (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [1; 5; 3]
+
+ inputs |> List.tryFind (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let input = [1; 2; 3]
+
+ input |> List.tryPick (fun n -> if n % 2 = 0 then Some (string n) else None)
+
+ Evaluates to
+ let input = [1; 2; 3]
+
+ input |> List.tryPick (fun n -> if n > 3 then Some (string n) else None)
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> List.truncate 2
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> List.truncate 6
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> List.truncate 0
+
+ Evaluates to the empty list.
+
+ let inputs =
+ [ [ 10; 20; 30 ]
+ [ 11; 21; 31 ] ]
+
+ inputs |> List.transpose
+
+ Evaluates to
+ let inputs = [ "banana"; "pear" ]
+
+ inputs |> List.tryHead
+
+ Evaluates to
+ let inputs : int list = []
+
+ inputs |> List.tryHead
+
+ Evaluates to
+ let inputs = [ 1; 2; 5 ]
+
+ inputs |> List.toSeq
+
+ Evaluates to
+ let inputs = [ 1; 2; 5 ]
+
+ inputs |> List.toArray
+
+ Evaluates to
+ let inputs = ["a"; "bb"; "ccc"; "d"]
+
+ inputs |> List.takeWhile (fun x -> x.Length < 3)
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> List.take 2
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> List.take 6
+
+ Throws
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> List.take 0
+
+ Evaluates to the empty list.
+
+ let inputs = ["a"; "bb"; "ccc"]
+
+ inputs |> List.tail
+
+ Evaluates to
+ let input = [ "aa"; "bbb"; "cc" ]
+
+ input |> List.sumBy (fun s -> s.Length)
+
+ Evaluates to
+ let input = [ 1; 5; 3; 2 ]
+
+ input |> List.sum
+
+ Evaluates to
+ let input = [8; 4; 3; 1; 6; 1]
+
+ input |> List.sortDescending
+
+ Evaluates to
+ let input = ["a"; "bbb"; "cccc"; "dd"]
+
+ input |> List.sortByDescending (fun s -> s.Length)
+
+ Evaluates to
+ let input = [8; 4; 3; 1; 6; 1]
+
+ let front, back = input |> List.splitAt 3
+
+ Evaluates
+ let input = [8; 4; 3; 1; 6; 1]
+
+ List.sort input
+
+ Evaluates to
+ let input = [ "a"; "bbb"; "cccc"; "dd" ]
+
+ input |> List.sortBy (fun s -> s.Length)
+
+ Evaluates to
+ let compareEntries (n1: int, s1: string) (n2: int, s2: string) =
+ let c = compare s1.Length s2.Length
+ if c <> 0 then c else
+ compare n1 n2
+
+ let input = [ (0,"aa"); (1,"bbb"); (2,"cc"); (3,"dd") ]
+
+ input |> List.sortWith compareEntries
+
+ Evaluates to
+ let inputs = ["a"; "bbb"; "cc"; "d"]
+
+ inputs |> List.skipWhile (fun x -> x.Length < 3)
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> List.skip 2
+
+ Evaluates to
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> List.skip 5
+
+ Throws
+ let inputs = ["a"; "b"; "c"; "d"]
+
+ inputs |> List.skip -1
+
+ Evaluates to
+ List.singleton 7
+
+ Evaluates to
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = [ In 1; Out 2; In 3 ]
+
+ (inputs, 0) ||> List.scanBack (fun charge acc ->
+ match charge with
+ | In i -> acc + i
+ | Out o -> acc - o)
+
+ Evaluates to
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = [In 1; Out 2; In 3]
+
+ (0, inputs) ||> List.scan (fun acc charge ->
+ match charge with
+ | In i -> acc + i
+ | Out o -> acc - o)
+
+ Evaluates to
+ let inputs = [ 0; 1; 2 ]
+
+ inputs |> List.rev
+
+ Evaluates to
+ List.replicate 3 "a"
+
+ Evaluates to
+ let inputs = [1; 3; 4; 2]
+
+ inputs |> List.reduceBack (fun a b -> a + b * 10)
+
+ Evaluates to
+ let inputs = [1; 3; 4; 2]
+
+ inputs |> List.reduce (fun a b -> a * 10 + b)
+
+ Evaluates to
+ let inputs = [1; 2; 3; 4]
+
+ inputs |> List.permute (fun x -> (x + 1) % 4)
+
+ Evaluates to
+ let input = [1; 2; 3]
+
+ input |> List.pick (fun n -> if n % 2 = 0 then Some (string n) else None)
+
+ Evaluates to
+ let input = [1; 2; 3]
+
+ input |> List.pick (fun n -> if n > 3 then Some (string n) else None)
+
+ Throws
+ let inputs = [1; 2; 3; 4]
+
+ let evens, odds = inputs |> List.partition (fun x -> x % 2 = 0)
+
+ Evaluates
+ let inputs = [1; 2; 3; 4]
+
+ inputs |> List.pairwise
+
+ Evaluates to
+ let inputs = seq { 1; 2; 5 }
+
+ inputs |> List.ofSeq
+
+ Evaluates to
+ let inputs = [| 1; 2; 5 |]
+
+ inputs |> List.ofArray
+
+ Evaluates to
+ let inputs = ["aaa"; "b"; "cccc"]
+
+ inputs |> List.minBy (fun s -> s.Length)
+
+ Evaluates to
+ let inputs = []
+
+ inputs |> List.minBy (fun (s: string) -> s.Length)
+
+ Throws
+ let inputs = [10; 12; 11]
+
+ inputs |> List.min
+
+ Evaluates to
+ let inputs = []
+
+ inputs |> List.min
+
+ Throws
+ let inputs = ["aaa"; "b"; "cccc"]
+
+ inputs |> List.maxBy (fun s -> s.Length)
+
+ Evaluates to
+ let inputs = []
+
+ inputs |> List.maxBy (fun (s: string) -> s.Length)
+
+ Throws
+ let inputs = [ 10; 12; 11 ]
+
+ inputs |> List.max
+
+ Evaluates to
+ let inputs = [ ]
+
+ inputs |> List.max
+
+ Throws
+ let inputs1 = ["a"; "bad"; "good"]
+ let inputs2 = [0; 2; 1]
+
+ (inputs1, inputs2) ||> List.mapi2 (fun i x y -> i, x[y])
+
+ Evaluates to
+ let inputs = [ 10; 10; 10 ]
+
+ inputs |> List.mapi (fun i x -> i + x)
+
+ Evaluates to
+ type Charge =
+ | In of int
+ | Out of int
+
+ let charges = [ In 1; Out 2; In 3 ]
+
+ let newCharges, balance =
+ (charges, 0) ||> List.mapFoldBack (fun charge acc ->
+ match charge with
+ | In i -> In (i*2), acc + i
+ | Out o -> Out (o*2), acc - o)
+
+ Evaluates
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = [ In 1; Out 2; In 3 ]
+
+ let newCharges, balance =
+ (0, inputs) ||> List.mapFold (fun acc charge ->
+ match charge with
+ | In i -> In (i*2), acc + i
+ | Out o -> Out (o*2), acc - o)
+
+ Evaluates
+ let inputs1 = [ "a"; "t"; "ti" ]
+ let inputs2 = [ "l"; "h"; "m" ]
+ let inputs3 = [ "l"; "e"; "e" ]
+
+ (inputs1, inputs2, inputs3) |||> List.map3 (fun x y z -> x + y + z)
+
+ Evaluates to
+ let inputs1 = ["a"; "bad"; "good"]
+ let inputs2 = [0; 2; 1]
+
+ (inputs1, inputs2) ||> List.map2 (fun x y -> x.[y])
+
+ Evaluates to
+ let inputs = [ "a"; "bbb"; "cc" ]
+
+ inputs |> List.map (fun x -> x.Length)
+
+ Evaluates to
+ [ "pear"; "banana" ] |> List.tryLast
+
+ Evaluates to
+ [ ] |> List.tryLast
+
+ Evaluates to
+ let inputs = [ "a"; "b"; "c" ]
+
+ inputs |> List.length
+
+ Evaluates to
+ [ "pear"; "banana" ] |> List.last
+
+ Evaluates to
+ [ ] |> List.last
+
+ Throws
+ let inputs1 = [ "a"; "b"; "c" ]
+ let inputs2 = [ "banana"; "pear"; "apple" ]
+
+ (inputs1, inputs2) ||> List.iteri2 (fun i s1 s2 -> printfn "Index %d: %s - %s" i s1 s2)
+
+ Evaluates to
+ Index 0: a - banana
+ Index 1: b - pear
+ Index 2: c - apple
+
+ in the console.
+
+ let inputs = [ "a"; "b"; "c" ]
+
+ inputs |> List.iteri (fun i v -> printfn "{i}: {v}")
+
+ Evaluates to
+ 0: a
+ 1: b
+ 2: c
+
+ in the console.
+
+ let inputs1 = [ "a"; "b"; "c" ]
+ let inputs2 = [ 1; 2; 3 ]
+
+ (inputs1, inputs2) ||> List.iter2 (printfn "%s: %i")
+
+ Evaluates to
+ a: 1
+ b: 2
+ c: 3
+
+ in the console.
+
+ let inputs = [ "a"; "b"; "c" ]
+
+ inputs |> List.iter (printfn "%s")
+
+ Evaluates to
+ a
+ b
+ c
+
+ in the console.
+
+ let inputs = [ "a"; "b"; "c" ]
+
+ inputs |> List.item 1
+
+ Evaluates to
+ let inputs = [ "a"; "b"; "c" ]
+
+ inputs |> List.item 4
+
+ Throws
+ [ ] |> List.isEmpty
+
+ Evaluates to
+ [ "pear"; "banana" ] |> List.isEmpty
+
+ Evaluates to
+ List.init 4 (fun v -> v + 5)
+
+ Evaluates to
+ List.init -5 (fun v -> v + 5)
+
+ Throws
+ let inputs = ["a"; "b"; "c"]
+
+ inputs |> List.indexed
+
+ Evaluates to
+ let inputs = ["banana"; "pear"]
+
+ inputs |> List.head
+
+ Evaluates to
+ [] |> List.head
+
+ Throws
+ let inputs = [1; 2; 3; 4; 5]
+
+ inputs |> List.groupBy (fun n -> n % 2)
+
+ Evaluates to
+ let inputs1 = [1; 2; 3]
+ let inputs2 = [1; 2; 3]
+
+ (inputs1, inputs2) ||> List.forall2 (=)
+
+ Evaluates to
+ let items1 = [2017; 1; 1]
+ let items2 = [2019; 19; 8]
+
+ (items1, items2) ||> List.forall2 (=)
+
+ Evaluates to
+ let items1 = [1; 2; 3]
+ let items2 = [1; 2]
+
+ (items1, items2) ||> List.forall2 (=)
+
+ Throws
+ let isEven a = a % 2 = 0
+
+ [2; 42] |> List.forall isEven // evaluates to true
+
+ [1; 2] |> List.forall isEven // evaluates to false
+
+ Count the positives, negatives and accumulate some text from back to front:
+ type Count =
+ { Positive: int
+ Negative: int
+ Text: string }
+
+ let inputs1 = [ -1; -2; -3 ]
+ let inputs2 = [ 3; 2; 1 ]
+ let initialState = {Positive = 0; Negative = 0; Text = ""}
+
+ (inputs1, inputs2, initialState) |||> List.foldBack2 (fun a b acc ->
+ let text = acc.Text + "(" + string a + "," + string b + ") "
+ if a + b >= 0 then
+ { acc with
+ Positive = acc.Positive + 1
+ Text = text }
+ else
+ { acc with
+ Negative = acc.Negative + 1
+ Text = text }
+ )
+
+ Evaluates to
+
+ { Positive = 2
+ Negative = 1
+ Text = "(-3,1) (-2,2) (-1,3) " }
+
+ Note
+ ([1..5], 0) ||> List.foldBack (fun v acc -> acc + v * v) // evaluates 55
+
+ Note
+ type Fruit = Apple | Pear | Orange
+
+ type BagItem = { fruit: Fruit; quantity: int }
+
+ let takeMore fruit (previous: BagItem list) =
+ let toTakeThisTime =
+ match previous with
+ | bagItem :: otherBagItems -> bagItem.quantity + 1
+ | [] -> 1
+ { fruit = fruit; quantity = toTakeThisTime } :: previous
+
+ let input = [ Apple; Pear; Orange ]
+
+ (input, []) ||> List.foldBack takeMore
+
+ Evaluates to
+
+ [{ fruit = Apple; quantity = 3 }
+ { fruit = Pear; quantity = 2 }
+ { fruit = Orange; quantity = 1 }]
+
+ Count the number of times the coins match:
+ type CoinToss = Head | Tails
+
+ let inputs1 = [Tails; Head; Tails]
+ let inputs2 = [Tails; Head; Head]
+
+ (0, inputs1, inputs2) |||> List.fold2 (fun acc input1 input2 ->
+ match (input1, input2) with
+ | Head, Head -> acc + 1
+ | Tails, Tails -> acc + 1
+ | _ -> acc)
+
+ Evaluates to
+ (0, [1..5]) ||> List.fold (fun s v -> s + v * v) // evaluates 55
+
+
+ type Fruit = Apple | Pear | Orange
+
+ type BagItem = { fruit: Fruit; quantity: int }
+
+ let takeMore (previous: BagItem list) fruit =
+ let toTakeThisTime =
+ match previous with
+ | bagItem :: otherBagItems -> bagItem.quantity + 1
+ | [] -> 1
+ { fruit = fruit; quantity = toTakeThisTime } :: previous
+
+ let inputs = [ Apple; Pear; Orange ]
+
+ ([], inputs) ||> List.fold takeMore
+
+ Evaluates to
+
+ [{ fruit = Orange; quantity = 3 }
+ { fruit = Pear; quantity = 2 }
+ { fruit = Apple; quantity = 1 }]
+
+
+ let input = [1, "Luke"; 2, "Kirk"; 3, "Kenobi"; 4, "Spock"]
+
+ let isEven x = 0 = x % 2
+
+ let isComingFromStarTrek (x,_) = isEven x
+
+ input |> List.filter isComingFromStarTrek
+
+ Evaluates to
+ let isEven x = 0 = x % 2
+
+ let isGreaterThan x y = y > x
+
+ let input = [1, "Luke"; 2, "Kirk"; 3, "Spock"; 4, "Kenobi"]
+
+ input |> List.findIndexBack (fun (x,_) -> isEven x) // evaluates 3
+ input |> List.findIndexBack (fun (x,_) -> x |> isGreaterThan 6) // raises an exception
+
+
+ let isEven x = 0 = x % 2
+
+ let isGreaterThan x y = y > x
+
+ let input = [1, "Luke"; 2, "Kirk"; 3, "Spock"; 4, "Kenobi"]
+
+ input |> List.findIndex (fun (x,_) -> isEven x) // evaluates 1
+ input |> List.findIndex (fun (x,_) -> x |> isGreaterThan 6) // raises an exception
+
+
+ let isEven x = 0 = x % 2
+
+ let isGreaterThan x y = y > x
+
+ let input = [1, "Luke"; 2, "Kirk"; 3, "Spock"; 4, "Kenobi"]
+
+ input |> List.findBack (fun (x,_) -> isEven x) // evaluates (4, "Kenobi")
+ input |> List.findBack (fun (x,_) -> x |> isGreaterThan 6) // raises an exception
+
+
+ let isEven x = 0 = x % 2
+
+ let isGreaterThan x y = y > x
+
+ let input = [1, "Luke"; 2, "Kirk"; 3, "Spock"; 4, "Kenobi"]
+
+ input |> List.find (fun (x,_) -> isEven x) // evaluates (2, "Kirk")
+ input |> List.find (fun (x,_) -> x |> isGreaterThan 6) // raises an exception
+
+
+ let anEvenSum a b = 0 = (a + b) % 2
+
+ ([1..4], [2..5])
+ ||> List.exists2 anEvenSum // evaluates false
+
+ ([1..4], [2;4;5;6])
+ ||> List.exists2 anEvenSum // evaluates true
+
+
+ let input = [1, "Kirk"; 2, "Spock"; 3, "Kenobi"]
+
+ input |> List.exists (fun x -> x = (3, "Kenobi")) // evaluates true
+
+ input |> List.exists (fun (n, name) -> n > 5) // evaluates false
+
+
+ [1] |> List.tryExactlyOne // evaluates Some 1
+ [1;2] |> List.tryExactlyOne // evaluates None
+ ([] : int list) |> List.tryExactlyOne // evaluates None
+
+
+ ["the chosen one"] |> List.exactlyOne // evaluates "the chosen one"
+
+
+ let input : string list = []
+
+ input |> List.exactlyOne
+
+ Will throw the exception:
+ [1..5] |> List.exactlyOne
+
+ Will throw the exception:
+ let input = [1, "Kirk"; 2, "Spock"; 3, "Kenobi"]
+
+ input |> List.except [3, "Kenobi"]
+
+ Evaluates to
+ [0..10] |> List.except [1..5] // evaluates [0; 6; 7; 8; 9; 10]
+
+
+ [1..5] |> List.except [0..10] // evaluates []
+
+
+ [1..10] |> List.splitInto 2
+
+ Evaluates to
+ [1..10] |> List.splitInto 4
+
+ Evaluates to
+ let input = ['H'; 'a'; 'p'; 'p'; 'y']
+
+ input |> List.countBy id
+
+ Evaluates
+ let isEven x = 0 = x % 2
+
+ let input = [6;1;2;3;1;4;5;5]
+
+ input |> List.distinctBy isEven // evaluates [6; 1]
+
+
+ let input = [6;1;2;3;1;4;5;5]
+
+ input |> List.distinct
+
+ Evaluates to
+ [1..9] |> List.contains 0
+
+ Evaluates to
+ [1..9] |> List.contains 3
+
+ Evaluates to
+ let input = [1, "SpongeBob"; 2, "Patrick"; 3, "Squidward"; 4, "Mr. Krabs"]
+
+ input |> List.contains (2, "Patrick")
+
+ Evaluates to
+ let input = [1, "SpongeBob"; 2, "Patrick"; 3, "Squidward"; 4, "Mr. Krabs"]
+
+ input |> List.contains (22, "Patrick")
+
+ Evaluates to
+ let input = [ [1;2]
+ [3;4;5]
+ [6;7;8;9] ]
+ input |> List.concat // evaluates [1; 2; 3; 4; 5; 6; 7; 8; 9]
+
+
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [1; 10]
+ let input2 = [1; 10]
+
+ (input1, input2) ||> List.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [1; 5]
+ let input2 = [1; 8]
+
+ (input1, input2) ||> List.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [1; 11]
+ let input2 = [1; 13]
+
+ (input1, input2) ||> List.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [1; 2]
+ let input2 = [1]
+
+ (input1, input2) ||> List.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [1]
+ let input2 = [1; 2]
+
+ (input1, input2) ||> List.compareWith closerToNextDozen
+
+ Evaluates to
+ [1..4] |> List.collect (fun x -> [1..x])
+
+ The sample evaluates to
+ [ 1..10 ] |> List.chunkBySize 3
+
+ Evaluates to
+
+ [ [ 1; 2; 3 ]
+ [ 4; 5; 6 ]
+ [ 7; 8; 9 ]
+ [ 10 ] ]
+
+
+ [ 1..5 ] |> List.chunkBySize 10
+
+ Evaluates to
+
+ [ [ 1; 2; 3; 4; 5 ] ]
+
+
+
+ let input1 = [ Some 1; None; Some 3; None ]
+
+ input1 |> List.choose id
+
+ Evaluates to
+
+ [ 1; 3 ]
+
+
+ type Happiness =
+ | AlwaysHappy
+ | MostOfTheTimeGrumpy
+
+ type People = { Name: string; Happiness: Happiness }
+
+ let takeJustHappyPersons person =
+ match person.Happiness with
+ | AlwaysHappy -> Some person.Name
+ | MostOfTheTimeGrumpy -> None
+
+ let candidatesForTheTrip =
+ [ { Name = "SpongeBob"
+ Happiness = AlwaysHappy }
+ { Name = "Patrick"
+ Happiness = AlwaysHappy }
+ { Name = "Squidward"
+ Happiness = MostOfTheTimeGrumpy } ]
+
+ candidatesForTheTrip
+ |> List.choose takeJustHappyPersons
+
+ Evaluates to
+
+ [ "SpongeBob"; "Patrick" ]
+
+
+ let input3: int option list = []
+
+ input3 |> List.choose id
+ Evaluates to:
+ empty list
+
+
+ let input4: string option list = [None; None]
+
+ input4 |> List.choose id
+ Evaluates to
+ empty list
+
+
+
+ let input5 = [ Some 1; None; Some 3; None ]
+
+ input5 |> List.choose id // evaluates [1; 3]
+
+
+ type People = { Name: string; Age: int }
+
+ let getAgeAsFloat person = float person.Age
+
+ let people =
+ [ { Name = "Kirk"; Age = 26 }
+ { Name = "Spock"; Age = 90 }
+ { Name = "McCoy"; Age = 37 } ]
+
+ people |> List.averageBy getAgeAsFloat
+
+ Evaluates to
+
+ 51.0
+
+
+ [1.0 .. 9.0] |> List.average
+
+ Evaluates to
+
+ 5.0
+
+
+ List.append [ 1..3 ] [ 4..7 ]
+
+ [ 4..7 ] |> List.append [ 1..3 ]
+
+ Evaluates to
+
+ [ 1; 2; 3; 4; 5; 6; 7 ]
+
+
+ let people = [ "Kirk"; "Spock"; "McCoy" ]
+ let numbers = [ 1; 2 ]
+
+ people |> List.allPairs numbers
+
+ Evaluates to
+
+ [ (1, "Kirk"); (1, "Spock"); (1, "McCoy"); (2, "Kirk"); (2, "Spock"); (2, "McCoy") ]
+
+
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomSampleBy Random.Shared.NextDouble 3
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomSampleWith Random.Shared 3
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomSample 3
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomChoicesBy Random.Shared.NextDouble 3
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomChoicesWith Random.Shared 3
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomChoices 3
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomChoiceBy Random.Shared.NextDouble
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomChoiceWith Random.Shared
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomChoice
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomShuffleInPlaceBy Random.Shared.NextDouble
+
+ After evaluation
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomShuffleInPlaceWith Random.Shared
+
+ After evaluation
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomShuffleInPlace
+
+ After evaluation
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomShuffleBy Random.Shared.NextDouble
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomShuffleWith Random.Shared
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2; 3; 4 |]
+
+ inputs |> Array.randomShuffle
+
+ Can evaluate to
+ let inputs = [| 0; 1; 2 |]
+
+ inputs |> Array.insertManyAt 1 [8; 9]
+
+ Evaluates to
+ let inputs = [| 0; 1; 2 |]
+
+ inputs |> Array.insertAt 1 9
+
+ Evaluates to
+ let inputs = [| 0; 1; 2 |]
+
+ inputs |> Array.updateAt 1 9
+
+ Evaluates to
+ let inputs = [| 0; 1; 2; 3 |]
+
+ inputs |> Array.removeManyAt 1 2
+
+ Evaluates to
+ let inputs = [| 0; 1; 2 |]
+
+ inputs |> Array.removeAt 1
+
+ Evaluates to
+ let numbers = [| 1; 2 |]
+ let names = [| "one"; "two" |]
+ let roman = [| "I"; "II" |]
+
+ Array.zip3 numbers names roman
+
+ Evaluates to
+ let numbers = [|1; 2|]
+ let names = [|"one"; "two"|]
+
+ Array.zip numbers names
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.windowed 3
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4 |]
+
+ inputs |> Array.where (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| (1, "one", "I"); (2, "two", "II") |]
+
+ let numbers, names, roman = inputs |> Array.unzip3
+
+ Evaluates
+ let inputs = [| (1, "one"); (2, "two") |]
+
+ let numbers, names = inputs |> Array.unzip
+
+ Evaluates
+ 1 |> Array.unfold (fun state -> if state > 100 then None else Some (state, state * 2))
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.tryFindIndexBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 3; 5; 7 |]
+
+ inputs |> Array.tryFindIndexBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c" |]
+
+ inputs |> Array.tryItem 1
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c" |]
+
+ inputs |> Array.tryItem 4
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.tryFindIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 3; 5; 7 |]
+
+ inputs |> Array.tryFindIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.tryFindBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 5; 3 |]
+
+ inputs |> Array.tryFindBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 2; 3 |]
+
+ inputs |> Array.tryFind (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 5; 3 |]
+
+ inputs |> Array.tryFind (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c"; "d" |]
+
+ inputs |> Array.truncate 2
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c"; "d" |]
+
+ inputs |> Array.truncate 6
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c"; "d" |]
+
+ inputs |> Array.truncate 0
+
+ Evaluates to
+ let inputs =
+ [| [| 10; 20; 30 |]
+ [| 11; 21; 31 |] |]
+
+ inputs |> Array.transpose
+
+ Evaluates to
+ let inputs = [| 1; 2; 5 |]
+
+ inputs |> Array.toSeq
+
+ Evaluates to
+ let inputs = [| 1; 2; 5 |]
+
+ inputs |> Array.toList
+
+ Evaluates to
+ let inputs = [| "a"; "bb"; "ccc" |]
+
+ inputs |> Array.tail
+
+ Evaluates to
+ let inputs = [| "a"; "bb"; "ccc"; "d" |]
+
+ inputs |> Array.takeWhile (fun x -> x.Length < 3)
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c"; "d" |]
+
+ inputs |> Array.take 2
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c"; "d" |]
+
+ inputs |> Array.take 6
+
+ Throws
+ let inputs = [| "a"; "b"; "c"; "d" |]
+
+ inputs |> Array.take 0
+
+ Evaluates to
+ let input = [| "aa"; "bbb"; "cc" |]
+
+ input |> Array.sumBy (fun s -> s.Length)
+
+ Evaluates to
+ let input = [| 1; 5; 3; 2 |]
+
+ input |> Array.sum
+
+ Evaluates to
+ let input = [| "a"; "bbb"; "cccc"; "dd" |]
+
+ input |> Array.sortByDescending (fun s -> s.Length)
+
+ Evaluates to
+ let input = [| 8; 4; 3; 1; 6; 1 |]
+
+ input |> Array.sortDescending
+
+ Evaluates to
+ let input = [| 8; 4; 3; 1; 6; 1 |]
+
+ let front, back = input |> Array.splitAt 3
+
+ Evaluates
+ let array = [| 8; 4; 3; 1; 6; 1 |]
+
+ Array.sortInPlace array
+
+ After evaluation
+ let compareEntries (n1: int, s1: string) (n2: int, s2: string) =
+ let c = compare s1.Length s2.Length
+ if c <> 0 then c else
+ compare n1 n2
+
+ let array = [| (0,"aa"); (1,"bbb"); (2,"cc"); (3,"dd") |]
+
+ array |> Array.sortInPlaceWith compareEntries
+
+ After evaluation
+ let array = [| "a"; "bbb"; "cccc"; "dd" |]
+
+ array |> Array.sortInPlaceBy (fun s -> s.Length)
+
+ After evaluation
+ let compareEntries (n1: int, s1: string) (n2: int, s2: string) =
+ let c = compare s1.Length s2.Length
+ if c <> 0 then c else
+ compare n1 n2
+
+ let input = [| (0,"aa"); (1,"bbb"); (2,"cc"); (3,"dd") |]
+
+ input |> Array.sortWith compareEntries
+
+ Evaluates to
+ let input = [| "a"; "bbb"; "cccc"; "dd" |]
+
+ input |> Array.sortBy (fun s -> s.Length)
+
+ Evaluates to
+ let input = [| 8; 4; 3; 1; 6; 1 |]
+
+ Array.sort input
+
+ Evaluates to
+ let input = [| 0; 1; 2; 3; 4; 5 |]
+
+ input.[2..4]
+
+
+ let input = [| 0; 1; 2; 3; 4; 5 |]
+
+ Array.sub input 2 3
+
+ Evaluates to
+ let inputs = [| "a"; "bbb"; "cc"; "d" |]
+
+ inputs |> Array.skipWhile (fun x -> x.Length < 3)
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c"; "d" |]
+
+ inputs |> Array.skip 2
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c"; "d" |]
+
+ inputs |> Array.skip 5
+
+ Throws
+ let inputs = [| "a"; "b"; "c"; "d" |]
+
+ inputs |> Array.skip -1
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c" |]
+
+ Array.set inputs 1 "B"
+
+ After evaluation
+ let inputs = [| "a"; "b"; "c" |]
+
+ Array.set inputs 4 "d"
+
+ Throws
+ Array.singleton 7
+
+ Evaluates to
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = [| In 1; Out 2; In 3 |]
+
+ (inputs, 0) ||> Array.scanBack (fun charge acc ->
+ match charge with
+ | In i -> acc + i
+ | Out o -> acc - o)
+
+ Evaluates to
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = [| In 1; Out 2; In 3 |]
+
+ (0, inputs) ||> Array.scan (fun acc charge ->
+ match charge with
+ | In i -> acc + i
+ | Out o -> acc - o)
+
+ Evaluates to
+ Array.rev [| 0; 1; 2 |]
+
+ Evaluates to
+ Array.replicate 3 "a"
+
+ Evaluates to
+ let inputs = [| 1; 3; 4; 2 |]
+
+ inputs |> Array.reduceBack (fun a b -> a + b * 10)
+
+ Evaluates to
+ let inputs = [| 1; 3; 4; 2 |]
+
+ inputs |> Array.reduce (fun a b -> a * 10 + b)
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4 |]
+
+ inputs |> Array.permute (fun x -> (x + 1) % 4)
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4 |]
+
+ inputs |> Array.partition (fun x -> x % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4 |]
+
+ inputs |> Array.pairwise
+
+ Evaluates to
+ let inputs = seq { 1; 2; 5 }
+
+ inputs |> Array.ofSeq
+
+ Evaluates to
+ let inputs = [ 1; 2; 5 ]
+
+ inputs |> Array.ofList
+
+ Evaluates to
+ let inputs = [| "aaa"; "b"; "cccc" |]
+
+ inputs |> Array.minBy (fun s -> s.Length)
+
+ Evaluates to
+ let inputs: string array= [| |]
+
+ inputs |> Array.minBy (fun s -> s.Length)
+
+ Throws
+ let inputs = [| 10; 12; 11 |]
+
+ inputs |> Array.min
+
+ Evaluates to
+ let inputs: int array= [| |]
+
+ inputs |> Array.min
+
+ Throws
+ let inputs = [| "aaa"; "b"; "cccc" |]
+
+ inputs |> Array.maxBy (fun s -> s.Length)
+
+ Evaluates to
+ let inputs: string array= [| |]
+
+ inputs |> Array.maxBy (fun s -> s.Length)
+
+ Throws
+ let inputs = [| 10; 12; 11 |]
+
+ inputs |> Array.max
+
+ Evaluates to
+ let inputs: int array= [| |]
+
+ inputs |> Array.max
+
+ Throws
+ let inputs = [| 10; 10; 10 |]
+
+ inputs |> Array.mapi (fun i x -> i + x)
+
+ Evaluates to
+ let inputs1 = [| "a"; "bad"; "good" |]
+ let inputs2 = [| 0; 2; 1 |]
+
+ (inputs1, inputs2) ||> Array.mapi2 (fun i x y -> i, x[y])
+
+ Evaluates to
+ let inputs1 = [| "a"; "t"; "ti" |]
+ let inputs2 = [| "l"; "h"; "m" |]
+ let inputs3 = [| "l"; "e"; "e" |]
+
+ (inputs1, inputs2, inputs3) |||> Array.map3 (fun x y z -> x + y + z)
+
+ Evaluates to
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = [| In 1; Out 2; In 3 |]
+
+ let newCharges, balance =
+ (inputs, 0) ||> Array.mapFoldBack (fun charge acc ->
+ match charge with
+ | In i -> In (i*2), acc + i
+ | Out o -> Out (o*2), acc - o)
+
+ Evaluates Accumulate the charges, and double them as well
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = [| In 1; Out 2; In 3 |]
+
+ let newCharges, balance =
+ (0, inputs) ||> Array.mapFold (fun acc charge ->
+ match charge with
+ | In i -> In (i*2), acc + i
+ | Out o -> Out (o*2), acc - o)
+
+ Evaluates
+ let inputs1 = [| "a"; "bad"; "good" |]
+ let inputs2 = [| 0; 2; 1 |]
+
+ (inputs1, inputs2) ||> Array.map2 (fun x y -> x[y])
+
+ Evaluates to
+ let inputs = [| "a"; "bbb"; "cc" |]
+
+ inputs |> Array.map (fun x -> x.Length)
+
+ Evaluates to
+ [| "pear"; "banana" |] |> Array.tryLast
+
+ Evaluates to
+ [| |] |> Array.tryLast
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c" |]
+
+ inputs |> Array.length
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c" |]
+
+ inputs |> Array.item 1
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c" |]
+
+ inputs |> Array.item 4
+
+ Throws
+ [| "pear"; "banana" |] |> Array.last
+
+ Evaluates to
+ [| |] |> Array.last
+
+ Throws
+ let inputs1 = [| "a"; "b"; "c" |]
+ let inputs2 = [| "banana"; "pear"; "apple" |]
+
+ (inputs1, inputs2) ||> Array.iteri2 (fun i s1 s2 -> printfn "Index {i}: {s1} - {s2}")
+
+ Evaluates to
+ Index 0: a - banana
+ Index 1: b - pear
+ Index 2: c - apple
+
+ in the console.
+
+ let inputs = [| "a"; "b"; "c" |]
+
+ inputs |> Array.iteri (fun i v -> printfn "{i}: {v}")
+
+ Evaluates to
+ 0: a
+ 1: b
+ 2: c
+
+ in the console.
+
+ let inputs1 = [| "a"; "b"; "c" |]
+ let inputs2 = [| 1; 2; 3 |]
+
+ (inputs1, inputs2) ||> Array.iter2 (printfn "%s: %i")
+
+ Evaluates to
+ a: 1
+ b: 2
+ c: 3
+
+ in the console.
+
+ let inputs = [| "a"; "b"; "c" |]
+
+ inputs |> Array.iter (printfn "%s")
+
+ Evaluates to
+ a
+ b
+ c
+
+ in the console.
+
+ [| |] |> Array.isEmpty
+
+ Evaluates to
+ [| "pear"; "banana" |] |> Array.isEmpty
+
+ Evaluates to
+ let arr : int array = Array.zeroCreate 4
+
+ Evaluates to
+ Array.init 4 (fun v -> v + 5)
+
+ Evaluates to
+ Array.init -5 (fun v -> v + 5)
+
+ Throws
+ let inputs = [| "a"; "b"; "c" |]
+
+ inputs |> Array.indexed
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.groupBy (fun n -> n % 2)
+
+ Evaluates to
+ let inputs = [| "banana"; "pear" |]
+
+ inputs |> Array.head
+
+ Evaluates to
+ [| |] |> Array.head
+
+ Throws
+ let inputs = [| "a"; "b"; "c" |]
+
+ Array.get inputs 1
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c" |]
+
+ Array.get inputs 4
+
+ Throws Count the positives, negatives and accumulate some text from back to front:
+ type Count =
+ { Positive: int
+ Negative: int
+ Text: string }
+
+ let inputs1 = [| -1; -2; -3 |]
+ let inputs2 = [| 3; 2; 1 |]
+ let initialState = {Positive = 0; Negative = 0; Text = ""}
+
+ (inputs1, inputs2, initialState) |||> Array.foldBack2 (fun a b acc ->
+ let text = acc.Text + "(" + string a + "," + string b + ") "
+ if a + b >= 0 then
+ { acc with
+ Positive = acc.Positive + 1
+ Text = text }
+ else
+ { acc with
+ Negative = acc.Negative + 1
+ Text = text }
+ )
+
+ Evaluates to
+
+ { Positive = 2
+ Negative = 1
+ Text = "(-3,1) (-2,2) (-1,3) " }
+
+
+ type CoinToss = Head | Tails
+
+ let data1 = [| Tails; Head; Tails |]
+ let data2 = [| Tails; Head; Head |]
+
+ (0, data1, data2) |||> Array.fold2 (fun acc a b ->
+ match (a, b) with
+ | Head, Head -> acc + 1
+ | Tails, Tails -> acc + 1
+ | _ -> acc - 1)
+
+ Evaluates to
+ type Count =
+ { Positive: int
+ Negative: int
+ Text: string }
+
+ let sequence = [| 1; 0; -1; -2; 3 |]
+ let initialState = {Positive = 0; Negative = 0; Text = "" }
+
+ (sequence, initialState) ||> Array.foldBack (fun a acc ->
+ let text = acc.Text + " " + string a
+ if a >= 0 then
+ { acc with
+ Positive = acc.Positive + 1
+ Text = text }
+ else
+ { acc with
+ Negative = acc.Negative + 1
+ Text = text })
+
+ Evaluates to
+
+ { Positive = 2
+ Negative = 3
+ Text = " 3 -2 -1 0 1" }
+
+
+ type Charge =
+ | In of int
+ | Out of int
+
+ let inputs = [| In 1; Out 2; In 3 |]
+
+ (0, inputs) ||> Array.fold (fun acc charge ->
+ match charge with
+ | In i -> acc + i
+ | Out o -> acc - o)
+
+ Evaluates to
+ let inputs1 = [| 1; 2; 3 |]
+ let inputs2 = [| 1; 2; 3 |]
+
+ (inputs1, inputs2) ||> Array.forall2 (=)
+
+ Evaluates to
+ let items1 = [| 2017; 1; 1 |]
+ let items2 = [| 2019; 19; 8 |]
+
+ (items1, items2) ||> Array.forall2 (=)
+
+ Evaluates to
+ let items1 = [| 1; 2; 3 |]
+ let items2 = [| 1; 2 |]
+
+ (items1, items2) ||> Array.forall2 (=)
+
+ Throws
+ let isEven a = a % 2 = 0
+
+ [2; 42] |> Array.forall isEven // evaluates to true
+
+ [1; 2] |> Array.forall isEven // evaluates to false
+
+
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.findIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.findIndex (fun elm -> elm % 6 = 0)
+
+ Throws
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.findIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4; 5 |]
+ inputs |> Array.findIndex (fun elm -> elm % 6 = 0)
+
+ Throws
+ let inputs = [| 2; 3; 4 |]
+
+ inputs |> Array.findBack (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 2; 3; 4 |]
+
+ inputs |> Array.findBack (fun elm -> elm % 6 = 0)
+
+ Throws
+ let inputs = [| 1; 2; 3 |]
+
+ inputs |> Array.find (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 2; 3 |]
+
+ inputs |> Array.find (fun elm -> elm % 6 = 0)
+
+ Throws
+ let inputs = [| 1; 2; 3; 4 |]
+
+ inputs |> Array.filter (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs1 = [| 1; 2 |]
+ let inputs2 = [| 1; 2; 0 |]
+
+ (inputs1, inputs2) ||> Array.exists2 (fun a b -> a > b)
+
+ Evaluates to
+ let inputs1 = [| 1; 4 |]
+ let inputs2 = [| 1; 3; 5 |]
+
+ (inputs1, inputs2) ||> Array.exists2 (fun a b -> a > b)
+
+ Evaluates to
+ let input = [| 1; 2; 3; 4; 5 |]
+
+ input |> Array.exists (fun elm -> elm % 4 = 0)
+
+ Evaluates to
+ let input = [| 1; 2; 3; 4; 5 |]
+
+ input |> Array.exists (fun elm -> elm % 6 = 0)
+
+ Evaluates to
+ let original = [| 1; 2; 3; 4; 5 |]
+ let itemsToExclude = [| 1; 3; 5 |]
+
+ original |> Array.except itemsToExclude
+
+ Evaluates to
+ let inputs = [| "banana" |]
+
+ inputs |> Array.tryExactlyOne
+
+ Evaluates to
+ let inputs = [| "pear"; "banana" |]
+
+ inputs |> Array.tryExactlyOne
+
+ Evaluates to
+ let inputs: int array = [| |]
+
+ inputs |> Array.tryExactlyOne
+
+ Evaluates to
+ let inputs = [| "banana" |]
+
+ inputs |> Array.exactlyOne
+
+ Evaluates to
+ let inputs = [| "pear"; "banana" |]
+
+ inputs |> Array.exactlyOne
+
+ Throws
+ let inputs: int array = [| |]
+
+ inputs |> Array.exactlyOne
+
+ Throws
+ Array.empty // Evaluates to [| |]
+
+
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.splitInto 3
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.splitInto -1
+
+ Throws
+ let inputs = [| {Bar = 1 };{Bar = 1}; {Bar = 2}; {Bar = 3} |]
+
+ inputs |> Array.distinctBy (fun foo -> foo.Bar)
+
+ Evaluates to
+ let input = [| 1; 1; 2; 3 |]
+
+ input |> Array.distinct
+
+ Evaluates to
+ let input = [| 1; 2; 3 |]
+
+ input |> Array.chunkBySize 2
+
+ Evaluates to
+ let input = [| 1; 2; 3 |]
+
+ input |> Array.chunkBySize -2
+
+ Throws
+ let input = [| Some 1; None; Some 2 |]
+
+ input |> Array.choose id
+
+ Evaluates to
+ let input = [| 1; 2; 3 |]
+
+ input |> Array.choose (fun n -> if n % 2 = 0 then Some n else None)
+
+ Evaluates to
+ let input = [| 1; 2; 3 |]
+
+ input |> Array.pick (fun n -> if n % 2 = 0 then Some (string n) else None)
+
+ Evaluates to
+ let input = [| 1; 2; 3 |]
+
+ input |> Array.pick (fun n -> if n > 3 = 0 then Some (string n) else None)
+
+ Throws
+ let target = [| 0; 1; 2; 3; 4; 5 |]
+
+ Array.fill target 3 2 100
+
+ After evaluation
+ let input = [| 1; 2; 3 |]
+
+ input |> Array.tryPick (fun n -> if n % 2 = 0 then Some (string n) else None)
+
+ Evaluates to
+ let input = [| 1; 2; 3 |]
+
+ input |> Array.tryPick (fun n -> if n > 3 = 0 then Some (string n) else None)
+
+ Evaluates to
+ let inputs = [| "banana"; "pear" |]
+
+ inputs |> Array.tryHead
+
+ Evaluates to
+ let inputs : int array = [| |]
+
+ inputs |> Array.tryHead
+
+ Evaluates to
+ Array.create 4 "a"
+
+ Evaluates to a new array containing
+ let cell = ref "a"
+ let array = Array.create 2 cell
+ cell.Value <- "b"
+
+
+ Before evaluation of the last line,
+ type Foo = { Bar: string }
+
+ let inputs = [| {Bar = "a"}; {Bar = "b"}; {Bar = "a"} |]
+
+ inputs |> Array.countBy (fun foo -> foo.Bar)
+
+ Evaluates to
+ let source = [| 12; 13; 14 |]
+
+ Array.copy source
+
+ Evaluates to a new array containing
+ [| 1; 2 |] |> Array.contains 2 // evaluates to true
+ [| 1; 2 |] |> Array.contains 5 // evaluates to false
+
+
+ let inputs = [ [| 1; 2 |]; [| 3 |]; [| 4; 5 |] ]
+
+ inputs |> Array.concat
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [| 1; 10 |]
+ let input2 = [| 1; 10 |]
+
+ (input1, input2) ||> Array.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [| 1; 5 |]
+ let input2 = [| 1; 8 |]
+
+ (input1, input2) ||> Array.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [| 1; 11 |]
+ let input2 = [| 1; 13 |]
+
+ (input1, input2) ||> Array.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [| 1; 2 |]
+ let input2 = [| 1 |]
+
+ (input1, input2) ||> Array.compareWith closerToNextDozen
+
+ Evaluates to
+ let closerToNextDozen a b =
+ (a % 12).CompareTo(b % 12)
+
+ let input1 = [| 1 |]
+ let input2 = [| 1; 2 |]
+
+ (input1, input2) ||> Array.compareWith closerToNextDozen
+
+ Evaluates to
+ type Foo = { Bar: int array }
+
+ let input = [| {Bar = [| 1; 2 |]}; {Bar = [| 3; 4 |]} |]
+
+ input |> Array.collect (fun foo -> foo.Bar)
+
+ Evaluates to
+ let input = [[1; 2]; [3; 4]]
+
+ input |> Array.collect id
+
+ Evaluates to
+ let source = [| 12; 13; 14 |]
+ let target = [| 0; 1; 2; 3; 4; 5 |]
+ target[3..4] <- source[1..2]
+
+
+ let source = [| 12; 13; 14 |]
+ let target = [| 0; 1; 2; 3; 4; 5 |]
+
+ Array.blit source 1 target 3 2
+
+ After evaluation
+ type Foo = { Bar: float }
+
+ let input = [| {Bar = 2.0}; {Bar = 4.0} |]
+
+ input |> Array.averageBy (fun foo -> foo.Bar)
+
+ Evaluates to
+ type Foo = { Bar: float }
+
+ let input : Foo array = [| |]
+
+ input |> Array.averageBy (fun foo -> foo.Bar)
+
+ Throws
+ [| 1.0; 2.0; 6.0 |] |> Array.average
+
+ Evaluates to
+ [| |] |> Array.average
+
+ Throws
+ Array.append [| 1; 2 |] [| 3; 4 |]
+
+ Evaluates to
+ ([| 1; 2 |], [| 3; 4 |]) ||> Array.allPairs
+
+ Evaluates to
+
+ [| (1, 3); (1, 4); (2, 3); (2, 4) |]
+
+
+ let inputs = [| 1; 2; 3; 4 |]
+
+ inputs |> Array.Parallel.filter (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let numbers = [|1; 2|]
+ let names = [|"one"; "two"|]
+
+ Array.Parallel.zip numbers names
+
+ Evaluates to
+ let input = [| "a"; "bbb"; "cccc"; "dd" |]
+
+ input |> Array.Parallel.sortByDescending (fun s -> s.Length)
+
+ Evaluates to
+ let input = [| 8; 4; 3; 1; 6; 1 |]
+
+ input |> Array.Parallel.sortDescending
+
+ Evaluates to
+ let array = [| 8; 4; 3; 1; 6; 1 |]
+
+ Array.sortInPlace array
+
+ After evaluation
+ let compareEntries (n1: int, s1: string) (n2: int, s2: string) =
+ let c = compare s1.Length s2.Length
+ if c <> 0 then c else
+ compare n1 n2
+
+ let array = [| (0,"aa"); (1,"bbb"); (2,"cc"); (3,"dd") |]
+
+ array |> Array.Parallel.sortInPlaceWith compareEntries
+
+ After evaluation
+ let array = [| "a"; "bbb"; "cccc"; "dd" |]
+
+ array |> Array.Parallel.sortInPlaceBy (fun s -> s.Length)
+
+ After evaluation
+ let compareEntries (n1: int, s1: string) (n2: int, s2: string) =
+ let c = compare s1.Length s2.Length
+ if c <> 0 then c else
+ compare n1 n2
+
+ let input = [| (0,"aa"); (1,"bbb"); (2,"cc"); (3,"dd") |]
+
+ input |> Array.Parallel.sortWith compareEntries
+
+ Evaluates to
+ let input = [| "a"; "bbb"; "cccc"; "dd" |]
+
+ input |> Array.Parallel.sortBy (fun s -> s.Length)
+
+ Evaluates to
+ let input = [| 8; 4; 3; 1; 6; 1 |]
+
+ Array.Parallel.sort input
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4 |]
+
+ inputs |> Array.Parallel.partition (fun x -> x % 2 = 0)
+
+ Evaluates to
+ Array.Parallel.init 4 (fun v -> v + 5)
+
+ Evaluates to
+ let inputs = [| "a"; "b"; "c" |]
+
+ inputs |> Array.Parallel.iteri (fun i v -> printfn "{i}: {v}")
+
+ Evaluates to
+ 0: a
+ 2: c
+ 1: b
+
+
+ let inputs = [| "a"; "b"; "c" |]
+
+ inputs |> Array.Parallel.iter (printfn "%s")
+
+ Evaluates to
+ a
+ c
+ b
+
+
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.Parallel.groupBy (fun n -> n % 2)
+
+ Evaluates to
+ let inputs = [| 10; 10; 10 |]
+
+ inputs |> Array.Parallel.mapi (fun i x -> i + x)
+
+ Evaluates to
+ let inputs = [| "a"; "bbb"; "cc" |]
+
+ inputs |> Array.Parallel.map (fun x -> x.Length)
+
+ Evaluates to
+ type Foo = { Bar: int array }
+
+ let input = [| {Bar = [| 1; 2 |]}; {Bar = [| 3; 4 |]} |]
+
+ input |> Array.Parallel.collect (fun foo -> foo.Bar)
+
+ Evaluates to
+ let input = [| [| 1; 2 |]; [| 3; 4 |] |]
+
+ input |> Array.Parallel.collect id
+
+ Evaluates to
+ let input = [| Some 1; None; Some 2 |]
+
+ input |> Array.Parallel.choose id
+
+ Evaluates to
+ let input = [| 1; 2; 3 |]
+
+ input |> Array.Parallel.choose (fun n -> if n % 2 = 0 then Some n else None)
+
+ Evaluates to
+ type Foo = { Bar: float }
+
+ let input = [| {Bar = 2.0}; {Bar = 4.0} |]
+
+ input |> Array.Parallel.averageBy (fun foo -> foo.Bar)
+
+ Evaluates to
+ type Foo = { Bar: float }
+
+ let input : Foo array = [| |]
+
+ input |> Array.Parallel.averageBy (fun foo -> foo.Bar)
+
+ Throws
+ [| 1.0; 2.0; 6.0 |] |> Array.Parallel.average
+
+ Evaluates to
+ [| |] |> Array.Parallel.average
+
+ Throws
+ let input = [| "aa"; "bbb"; "cc" |]
+
+ input |> Array.Parallel.sumBy (fun s -> s.Length)
+
+ Evaluates to
+ let input = [| 1; 5; 3; 2 |]
+
+ input |> Array.Parallel.sum
+
+ Evaluates to
+ let inputs = [| "aaa"; "b"; "cccc" |]
+
+ inputs |> Array.Parallel.minBy (fun s -> s.Length)
+
+ Evaluates to
+ let inputs: string array= [| |]
+
+ inputs |> Array.Parallel.minBy (fun s -> s.Length)
+
+ Throws
+ let inputs = [| 10; 12; 11 |]
+
+ inputs |> Array.Parallel.min
+
+ Evaluates to
+ let inputs: int array= [| |]
+
+ inputs |> Array.Parallel.min
+
+ Throws
+ let inputs = [| "aaa"; "b"; "cccc" |]
+
+ inputs |> Array.Parallel.maxBy (fun s -> s.Length)
+
+ Evaluates to
+ let inputs: string array= [| |]
+
+ inputs |> Array.Parallel.maxBy (fun s -> s.Length)
+
+ Throws
+ let inputs = [| 10; 12; 11 |]
+
+ inputs |> Array.Parallel.max
+
+ Evaluates to
+ let inputs: int array= [| |]
+
+ inputs |> Array.Parallel.max
+
+ Throws
+ let inputs = [| "1"; "3"; "4"; "2" |]
+
+ inputs |> Array.Parallel.reduceBy (fun x -> int x) (+)
+
+ Evaluates to
+ let inputs = [| 1; 3; 4; 2 |]
+
+ inputs |> Array.Parallel.reduce (fun a b -> a + b)
+
+ Evaluates to
+ let input = [| 1; 2; 3 |]
+
+ input |> Array.Parallel.tryPick (fun n -> if n % 2 = 0 then Some (string n) else None)
+
+ Evaluates to
+ let input = [| 1; 2; 3 |]
+
+ input |> Array.Parallel.tryPick (fun n -> if n > 3 = 0 then Some (string n) else None)
+
+ Evaluates to
+ let inputs = [| 1; 2; 3; 4; 5 |]
+
+ inputs |> Array.Parallel.tryFindIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 3; 5; 7 |]
+
+ inputs |> Array.Parallel.tryFindIndex (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 2; 3 |]
+
+ inputs |> Array.Parallel.tryFind (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let inputs = [| 1; 5; 3 |]
+
+ inputs |> Array.Parallel.tryFind (fun elm -> elm % 2 = 0)
+
+ Evaluates to
+ let input = [| 1; 2; 3; 4; 5 |]
+
+ input |> Array.Parallel.exists (fun elm -> elm % 4 = 0)
+
+ Evaluates to
+ let input = [| 1; 2; 3; 4; 5 |]
+
+ input |> Array.Parallel.exists (fun elm -> elm % 6 = 0)
+
+ Evaluates to
+ let isEven a = a % 2 = 0
+
+ [2; 42] |> Array.Parallel.forall isEven // evaluates to true
+
+ [1; 2] |> Array.Parallel.forall isEven // evaluates to false
+
+
+ let array: float[,,,] = Array4D.zeroCreate 2 3 4 5
+
+ array[0,2,1,3] <- 5.0
+
+
+ let array = Array4D.zeroCreate 2 3 4 5
+
+ Array4D.2et array 0 2 1 3 5.0
+
+
+ let array: float[,,,] = Array4D.zeroCreate 2 3 4 5
+
+ array[0,2,1,3]
+
+
+ let array = Array4D.zeroCreate 2 3 4 5
+
+ Array4D.get array 0 2 1 3
+
+
+ let array : float[,,,] = Array4D.zeroCreate 2 3 3 5
+
+ After evaluation
+ let array = Array4D.init 2 3 4 5 (fun i j k -> 100*i + 10*j + k)
+
+ array |> Array4D.length4
+
+ Evaluates to
+ let array = Array4D.init 2 3 4 5 (fun i j k -> 100*i + 10*j + k)
+
+ array |> Array4D.length3
+
+ Evaluates to
+ let array = Array4D.init 2 3 4 5 (fun i j k -> 100*i + 10*j + k)
+
+ array |> Array4D.length2
+
+ Evaluates to
+ let array = Array4D.init 2 3 4 5 (fun i j k -> 100*i + 10*j + k)
+
+ array |> Array4D.length1
+
+ Evaluates to
+ Array4D.init 2 2 2 2 (fun i j k l -> i*1000+j*100+k*10+l)
+
+ Evaluates to a 2x2x2x2 array with contents
+ Array4D.create 2 2 2 2 1
+
+ Evaluates to a 2x2x2x2 array with all entries
+ let array : float[,,] = Array3D.zeroCreate 2 3 3
+
+ After evaluation
+ let array = Array3D.zeroCreate 2 3 3
+
+ array[0,2,1] < 4.0
+
+ Evaluates to
+ let array = Array3D.zeroCreate 2 3 3
+
+ Array3D.set array 0 2 1 4.0
+
+ After evaluation
+ let inputs = Array3D.zeroCreate 2 3 3
+
+ inputs |> Array3D.mapi (fun i j k v -> 100*i + 10*j + k)
+
+ Evaluates to a 2x3x3 array with contents
+ let inputs = Array3D.init 2 3 3 (fun i j k -> 100*i + 10*j + k)
+
+ inputs |> Array3D.map (fun v -> 2 * v)
+
+ Evaluates to a 2x3x3 array with contents
+ let array = Array3D.init 2 3 4 (fun i j k -> 100*i + 10*j + k)
+
+ array |> Array3D.length3
+
+ Evaluates to
+ let array = Array3D.init 2 3 4 (fun i j k -> 100*i + 10*j + k)
+
+ array |> Array3D.length2
+
+ Evaluates to
+ let array = Array3D.init 2 3 4 (fun i j k -> 100*i + 10*j + k)
+
+ array |> Array3D.length1
+
+ Evaluates to
+ let inputs = Array3D.init 2 2 3 (fun i j k -> 100*i + 10*j + k)
+
+ inputs |> Array3D.iteri (fun i j k v -> printfn $"value at ({i},{j},{k}) = {v}")
+
+ Evaluates to
+ value at (0,0,0) = 0
+ value at (0,0,1) = 1
+ value at (0,0,2) = 2
+ value at (0,1,0) = 10
+ value at (0,1,1) = 11
+ value at (0,1,2) = 12
+ value at (1,0,0) = 100
+ value at (1,0,1) = 101
+ value at (1,0,2) = 102
+ value at (1,1,0) = 110
+ value at (1,1,1) = 111
+ value at (1,1,2) = 112
+
+ in the console.
+
+ let inputs = Array3D.init 2 2 3 (fun i j k -> 100*i + 10*j + k)
+
+ inputs |> Array3D.iter (fun v -> printfn $"value = {v}")
+
+ Evaluates to
+ value = 0
+ value = 1
+ value = 2
+ value = 10
+ value = 11
+ value = 12
+ value = 100
+ value = 101
+ value = 102
+ value = 110
+ value = 111
+ value = 112
+
+ in the console.
+
+ let array = Array3D.init 2 3 3 (fun i j k -> 100*i + 10*j + k)
+
+ array[0,2,1]
+
+ Evaluates to
+ let array = Array3D.init 2 3 3 (fun i j k -> 100*i + 10*j + k)
+
+ Array3D.get array 0 2 1
+
+ Evaluates to
+ Array3D.init 2 2 3 (fun i j k -> 100*i + 10*j + k)
+
+ Evaluates to a 2x2x3 array with contents
+ Array3D.create 2 2 3 1
+
+ Evaluates to a 2x3 array with contents
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.maxKeyValue // evaluates to (2, "b")
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.minKeyValue // evaluates to (1, "a")
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.values // evaluates to seq ["a"; "b"]
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.keys // evaluates to seq [1; 2]
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.count // evaluates to 2
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.tryFindKey (fun n s -> n = s.Length) // evaluates to Some 1
+ sample |> Map.tryFindKey (fun n s -> n < s.Length) // evaluates to None
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.findKey (fun n s -> n = s.Length) // evaluates to 1
+ sample |> Map.findKey (fun n s -> n < s.Length) // throws KeyNotFoundException
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.tryFind 1 // evaluates to Some "a"
+ sample |> Map.tryFind 3 // evaluates to None
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.remove 1 // evaluates to map [(2, "b")]
+ sample |> Map.remove 3 // equal to sample
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.partition (fun n s -> n = s.Length) // evaluates to (map [(1, "a")], map [(2, "b")])
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.containsKey 1 // evaluates to true
+ sample |> Map.containsKey 3 // evaluates to false
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.map (fun n s -> sprintf "%i %s" n s) // evaluates to map [(1, "1 a"); (2, "2 b")]
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.forall (fun n s -> n >= s.Length) // evaluates to true
+ sample |> Map.forall (fun n s -> n = s.Length) // evaluates to false
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.filter (fun n s -> n = s.Length) // evaluates to map [(1, "a")]
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.exists (fun n s -> n = s.Length) // evaluates to true
+ sample |> Map.exists (fun n s -> n < s.Length) // evaluates to false
+
+
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.iter (fun n s -> printf "%i %s " n s)
+
+ Prints
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ ("initial", sample) ||> Map.fold (fun state n s -> sprintf "%s %i %s" state n s)
+
+ Evaluates to
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ (sample, "initial") ||> Map.foldBack (fun n s state -> sprintf "%i %s %s" n s state)
+
+ Evaluates to
+ let sample = Map [ (1, "a"); (2, "b"); (10, "ccc"); (20, "ddd") ]
+
+ sample |> Map.pick (fun n s -> if n > 5 && s.Length > 2 then Some s else None)
+
+ Evaluates to
+ let sample = Map [ (1, "a"); (2, "b"); (10, "ccc"); (20, "ddd") ]
+
+ sample |> Map.pick (fun n s -> if n > 5 && s.Length > 4 then Some s else None)
+
+ Raises
+ let sample = Map [ (1, "a"); (2, "b"); (10, "ccc"); (20, "ddd") ]
+
+ sample |> Map.tryPick (fun n s -> if n > 5 && s.Length > 2 then Some s else None)
+
+ Evaluates to
+ let sample = Map [ (1, "a"); (2, "b"); (10, "ccc"); (20, "ddd") ]
+
+ sample |> Map.tryPick (fun n s -> if n > 5 && s.Length > 4 then Some s else None)
+
+ Evaluates to
+ let sample = Map [ (1, "a"); (2, "b") ]
+
+ sample |> Map.find 1 // evaluates to "a"
+ sample |> Map.find 3 // throws KeyNotFoundException
+
+
+ let emptyMap = Map.empty<int, string>
+
+
+ let emptyMap = Map.empty<int, string>
+ emptyMap |> Map.isEmpty // evaluates to true
+
+ let notEmptyMap = Map [ (1, "a"); (2, "b") ]
+ emptyMap |> Map.isEmpty // evaluates to false
+
+
+ let input = Map [ (1, "a"); (2, "b") ]
+
+ input |> Map.toArray // evaluates to [|(1, "a"); (2, "b")|]
+
+
+ let input = Map [ (1, "a"); (2, "b") ]
+
+ input |> Map.toList // evaluates to [(1, "a"); (2, "b")]
+
+
+ let input = Map [ (1, "a"); (2, "b") ]
+
+ input |> Map.toSeq // evaluates to seq [(1, "a"); (2, "b")]
+
+
+ let input = seq { (1, "a"); (2, "b") }
+
+ input |> Map.ofSeq // evaluates to map [(1, "a"); (2, "b")]
+
+
+ let input = [| (1, "a"); (2, "b") |]
+
+ input |> Map.ofArray // evaluates to map [(1, "a"); (2, "b")]
+
+
+ let input = [ (1, "a"); (2, "b") ]
+
+ input |> Map.ofList // evaluates to map [(1, "a"); (2, "b")]
+
+
+ let input = Map [ (1, "a"); (2, "b") ]
+
+ input |> Map.change 1 (fun x ->
+ match x with
+ | Some s -> Some (s + "z")
+ | None -> None
+ ) // evaluates to map [(1, "az"); (2, "b")]
+
+
+ let input = Map [ (1, "a"); (2, "b") ]
+
+ input |> Map.add 3 "c" // evaluates to map [(1, "a"); (2, "b"); (3, "c")]
+ input |> Map.add 2 "aa" // evaluates to map [(1, "a"); (2, "aa")]
+
+
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(2).Add(3).Add(4)
+ printfn $"The difference of {set1} and {set2} is {Set.difference set1 set2}"
+
+ The sample evaluates to the following output:
+ let set = Set.ofSeq [1, 2, 3]
+ printfn $"The set is {set} and type is {set.GetType().Name}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ let seq = Set.toSeq set
+ printfn $"The set is {set} and type is {seq.GetType().Name}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ let array = Set.toArray set
+ printfn$ "The set is {set} and type is {array.GetType().Name}"
+
+ The sample evaluates to the following output:
+ let set = Set.ofArray [|1, 2, 3|]
+ printfn $"The set is {set} and type is {set.GetType().Name}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ let list = Set.toList set
+ printfn $"The set is {list} and type is {list.GetType().Name}"
+
+ The sample evaluates to the following output:
+ let set = Set.ofList [1, 2, 3]
+ printfn $"The set is {set} and type is {set.GetType().Name}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ printfn $"The min element of {set} is {Set.minElement set}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ printfn $"The min element of {set} is {Set.minElement set}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ printfn $"The set without 1 is {Set.remove 1 set}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3).Add(4)
+ printfn $"The set with even numbers is {Set.partition (fun x -> x % 2 = 0) set}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ Set.iter (fun x -> printfn $"The set contains {x}") set
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(2).Add(3)
+ printfn $"Is the set empty? {set.IsEmpty}"
+
+ The sample evaluates to the following output:
+ let headersByFile = seq{
+ yield [ "id"; "name"; "date"; "color" ]
+ yield [ "id"; "age"; "date" ]
+ yield [ "id"; "sex"; "date"; "animal" ]
+ }
+ headersByFile
+ |> Seq.map Set.ofList
+ |> Set.intersectMany
+ |> printfn "The intersection of %A is %A" headersByFile
+
+ The sample evaluates to the following output:
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(2).Add(3).Add(4)
+ printfn $"The union of {set1} and {set2} is {(Set.union set1 set2)}"
+
+ The sample evaluates to the following output:
+ let headersByFile = seq{
+ yield [ "id"; "name"; "date"; "color" ]
+ yield [ "id"; "age"; "date" ]
+ yield [ "id"; "sex"; "date"; "animal" ]
+ }
+ headersByFile
+ |> Seq.map Set.ofList
+ |> Set.intersectMany
+ |> printfn "The intersection of %A is %A" headersByFile
+
+ The sample evaluates to the following output:
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(2).Add(3).Add(4)
+ printfn $"The intersection of {set1} and {set2} is {Set.intersect set1 set2}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ printfn $"Does the set contain even numbers? {Set.forall (fun x -> x % 2 = 0) set}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ printfn $"The sum of the set is {Set.foldBack (+) set 0}"
+ printfn $"The set is {Set.foldBack (fun x acc -> x :: acc) set []}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ printfn $"The sum of the set is {Set.fold (+) 0 set}"
+ printfn $"The product of the set is {Set.fold (*) 1 set}"
+ printfn $"The reverse of the set is {Set.fold (fun x y -> y :: x) [] set}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ printfn $"The set with doubled values is {Set.map (fun x -> x * 2) set}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3).Add(4)
+ printfn $"The set with even numbers is {Set.filter (fun x -> x % 2 = 0) set}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ printfn $"Does the set contain 1? {Set.exists (fun x -> x = 1) set}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(2).Add(3)
+ printfn $"The set has {set.Count} elements"
+
+ The sample evaluates to the following output:
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(1).Add(2).Add(3).Add(4)
+ printfn $"Is {set1} a proper superset of {set2}? {Set.isProperSuperset set1 set2}"
+
+ The sample evaluates to the following output:
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(1).Add(2).Add(3).Add(4)
+ printfn $"Is {set1} a superset of {set2}? {Set.isSuperset set1 set2}"
+
+ The sample evaluates to the following output:
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(1).Add(2).Add(3).Add(4)
+ printfn $"Is {set1} a proper subset of {set2}? {Set.isProperSubset set1 set2}"
+
+ The sample evaluates to the following output:
+ let set1 = Set.empty.Add(1).Add(2).Add(3)
+ let set2 = Set.empty.Add(1).Add(2).Add(3).Add(4)
+ printfn $"Is {set1} a subset of {set2}? {Set.isSubset set1 set2}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(2).Add(3)
+ printfn $"Does the set contain 1? {set.Contains(1))}"
+
+ The sample evaluates to the following output:
+ let set = Set.empty.Add(1).Add(1).Add(2)
+ printfn $"The new set is: {set}"
+
+ The sample evaluates to the following output:
+ Set.singleton 7
+
+ Evaluates to
+ Set.empty<int>
+
+ Evaluates to
+ type CoinToss = Heads | Tails
+
+ typeof<CoinToss>
+ |> FSharpType.GetUnionCases
+ |> Array.map (fun x -> $"{x.Name} has tag {x.Tag}")
+
+ Evaluates to
+ type Weather = Rainy | Sunny
+
+ typeof<Weather>
+ |> FSharpType.GetUnionCases
+ |> Array.map (fun x -> x.Name)
+
+ Evaluates to
+ type Weather = Rainy | Sunny
+
+ let rainy =
+ typeof<Weather>
+ |> FSharpType.GetUnionCases
+ |> Array.head
+
+ rainy.DeclaringType
+
+ Evaluates to a value of type
+ type Shape =
+ | Rectangle of width : float * length : float
+ | Circle of radius : float
+ | Prism of width : float * float * height : float
+
+ typeof<Shape>
+ |> FSharpType.GetUnionCases
+ |> Array.map (fun unionCase ->
+ unionCase.GetFields()
+ |> Array.map (fun fieldInfo ->
+ fieldInfo.Name,
+ fieldInfo.PropertyType.Name))
+
+ Evaluates to
+
+ [|[|("width", "Double"); ("length", "Double")|];
+ [|("radius", "Double")|];
+ [|("width", "Double"); ("Item2", "Double"); ("height", "Double")|]|]
+
+
+ type Signal(signal: string) =
+ inherit System.Attribute()
+ member this.Signal = signal
+
+ type Answer =
+ | [<Signal("Thumbs up")>] Yes
+ | [<Signal("Thumbs down")>] No
+
+ let answerYes =
+ typeof<Answer>
+ |> FSharpType.GetUnionCases
+ |> Array.find (fun x -> x.Name = "Yes")
+
+ answerYes.GetCustomAttributesData()
+
+ Evaluates to
+
+ [|[FSI_0150+Signal("Thumbs up")]
+ {AttributeType = FSI_0150+Signal;
+ Constructor = Void .ctor(System.String);
+ ConstructorArguments = seq ["Thumbs up"];
+ NamedArguments = seq [];};
+ [Microsoft.FSharp.Core.CompilationMappingAttribute((Microsoft.FSharp.Core.SourceConstructFlags)8, (Int32)0)]
+ {AttributeType = Microsoft.FSharp.Core.CompilationMappingAttribute;
+ Constructor = Void .ctor(Microsoft.FSharp.Core.SourceConstructFlags, Int32);
+ ConstructorArguments = seq
+ [(Microsoft.FSharp.Core.SourceConstructFlags)8;
+ (Int32)0];
+ NamedArguments = seq [];}|]
+
+
+ type Signal(signal: string) =
+ inherit System.Attribute()
+ member this.Signal = signal
+
+ type Answer =
+ | [<Signal("Thumbs up")>] Yes
+ | [<Signal("Thumbs down")>] No
+
+ typeof<Answer>
+ |> FSharpType.GetUnionCases
+ |> Array.map (fun x -> x.GetCustomAttributes(typeof<Signal>))
+
+ Evaluates to
+
+ [|[|FSI_0147+Signal {Signal = "Thumbs up";
+ TypeId = FSI_0147+Signal;}|];
+ [|FSI_0147+Signal {Signal = "Thumbs down";
+ TypeId = FSI_0147+Signal;}|]|]
+
+
+ type Weather =
+ | Rainy
+ | Sunny
+
+ typeof<Weather>
+ |> FSharpType.GetUnionCases
+ |> Array.map (fun x -> x.GetCustomAttributes())
+
+ Evaluates to
+
+ [|[|Microsoft.FSharp.Core.CompilationMappingAttribute
+ {ResourceName = null;
+ SequenceNumber = 0;
+ SourceConstructFlags = UnionCase;
+ TypeDefinitions = null;
+ TypeId = Microsoft.FSharp.Core.CompilationMappingAttribute;
+ VariantNumber = 0;}|];
+ [|Microsoft.FSharp.Core.CompilationMappingAttribute
+ {ResourceName = null;
+ SequenceNumber = 1;
+ SourceConstructFlags = UnionCase;
+ TypeDefinitions = null;
+ TypeId = Microsoft.FSharp.Core.CompilationMappingAttribute;
+ VariantNumber = 0;}|]|]
+
+
+ open FSharp.Quotations
+
+ let expr1 = <@ 1 + 1 @>
+
+ expr1.Raw
+
+ Evaluates to the same quotation as
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let sampleQuotation = <@ 1 + 1 @>
+
+ sampleQuotation.Type
+
+ Evaluates to
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let sampleQuotation = <@ 1 + 1 @>
+
+ sampleQuotation.CustomAttributes
+
+ Evaluates to a list of expressions containing one custom attribute for the source location of the quotation literal.
+
+ open FSharp.Quotations
+
+ Expr.WithValue(box 1, typeof<int>, <@ 2 - 1 @>)
+
+ Evaluates to a quotation that displays as
+ open FSharp.Quotations
+
+ Expr.WithValue(1, <@ 2 - 1 @>)
+
+ Evaluates to a quotation that displays as
+ open FSharp.Quotations
+
+ let guardExpr = <@ true @>
+ let bodyExpr = <@ () @>
+
+ Expr.WhileLoop(guardExpr, bodyExpr)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ let vVar = Var("v", typeof<int>, isMutable=true)
+
+ Expr.VarSet(vVar, <@ 5 @>)
+
+ Evaluates to a quotation displayed as
+ open FSharp.Quotations
+
+ let vVar = Var("v", typeof<int>)
+
+ Expr.Var(vVar)
+
+ Evaluates to a quotation displayed as
+ open FSharp.Quotations
+
+ Expr.ValueWithName(box 1, typeof<int>, "name")
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ Expr.ValueWithName(1, "name")
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ Expr.Value(1)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ Expr.Value(box 1, typeof<int>)
+
+ Evaluates to a quotation with the same structure as
+ open System
+ open FSharp.Quotations
+ open FSharp.Reflection
+
+ let ucCons = FSharpType.GetUnionCases(typeof<int list>)[1]
+
+ Expr.UnionCaseTest(<@ [11] @>, ucCons)
+
+ Evaluates to a quotation that displays as
+ open FSharp.Quotations
+
+ let obj = box 1
+
+ Expr.TypeTest( <@ obj @>, typeof<int>)
+
+ Evaluates to quotation that displays as
+ open FSharp.Quotations
+
+ let tupExpr = <@ (1, 2, 3) @>
+
+ Expr.TupleGet(tupExpr, 1)
+
+ Evaluates to quotation that displays as
+ open System
+ open FSharp.Quotations
+
+ let exnVar = Var("exn", typeof<exn>)
+
+ Expr.TryWith(<@ 1+1 @>, exnVar, <@ 1 @>, exnVar, <@ 2+2 @>)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ [<ReflectedDefinition>]
+ let f x = x + 1
+
+ let methInfo =
+ match <@ f 1 @> with
+ | Call(_, mi, _) -> mi
+ | _ -> failwith "call expected"
+
+ Expr.TryGetReflectedDefinition(methInfo)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ [<ReflectedDefinition>]
+ module Methods =
+ let f x = (x, x)
+
+ let methInfoGeneric =
+ match <@ Methods.f (1, 2) @> with
+ | Call(_, mi, _) -> mi.GetGenericMethodDefinition()
+ | _ -> failwith "call expected"
+
+ let methInfoAtString = methInfoGeneric.MakeGenericMethod(typeof<string>)
+
+ Expr.TryGetReflectedDefinition(methInfoAtString)
+
+ Evaluates to a quotation with the same structure as
+ open System
+ open FSharp.Quotations
+
+ Expr.TryFinally(<@ 1+1 @>, <@ Console.WriteLine("finally") @>)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ let expr1 = <@ 1 + 1 @>
+
+ expr1.ToString(true)
+
+ Evaluates
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let sampleQuotation = <@ fun v -> v * v @>
+
+ let v, body =
+ match sampleQuotation with
+ | Lambda(v, body) -> (v, body)
+ | _ -> failwith "unreachable"
+
+ body.Substitute(function v2 when v = v2 -> Some <@ 1 + 1 @> | _ -> None)
+
+ Evaluates to
+ open System
+ open FSharp.Quotations
+
+ Expr.Sequential(<@ Console.WriteLine("a") @>, <@ Console.WriteLine("b") @>)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ Expr.QuoteTyped(<@ 1 @>)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ Expr.QuoteRaw(<@ 1 @>)
+
+ Evaluates to a quotation with the same structure as
+ open System
+ open System.Collections.Generic
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let propInfo =
+ match <@ Console.BackgroundColor <- ConsoleColor.Red @> with
+ | PropertySet(None, pi, _, _) -> pi
+ | _ -> failwith "property get expected"
+
+ Expr.PropertySet(propInfo, <@ ConsoleColor.Blue @>)
+
+ Evaluates to a quotation with the same structure as
+ open System
+ open System.Collections.Generic
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let propInfo =
+ match <@ (new List<int>()).Capacity @> with
+ | PropertyGet(Some _, pi, _) -> pi
+ | _ -> failwith "property get expected"
+
+ let objExpr = <@ (new List<int>()) @>
+
+ Expr.PropertySet(objExpr, propInfo, <@ 6 @>)
+
+ Evaluates to a quotation with the same structure as
+ open System
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let propInfo =
+ match <@ Console.Out @> with
+ | PropertyGet(None, pi, _) -> pi
+ | _ -> failwith "property get expected"
+
+ Expr.PropertyGet(propInfo)
+
+ Evaluates to a quotation with the same structure as
+ open System
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let propInfo =
+ match <@ "a".Length @> with
+ | PropertyGet(Some _, pi, _) -> pi
+ | _ -> failwith "property get expected"
+
+ let objExpr = <@ "bb" @>
+
+ Expr.PropertyGet(objExpr, propInfo)
+
+ Evaluates to a quotation with the same structure as
+ open System
+ open FSharp.Quotations
+ open FSharp.Reflection
+
+ let ucCons = FSharpType.GetUnionCases(typeof<int list>)[1]
+
+ Expr.NewUnionCase(ucCons, [ <@ 10 @>; <@ [11] @> ])
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ Expr.NewTuple([ <@ 1 @>; <@ "a" @> ])
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ Expr.NewStructTuple( [ <@ 1 @>; <@ "a" @> ])
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ Expr.NewStructTuple(typeof<struct (int * int)>.Assembly, [ <@ 1 @>; <@ "a" @> ])
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ type R = { Y: int; X: string }
+
+ Expr.NewRecord(typeof<R>, [ <@ 1 @>; <@ "a" @> ])
+
+ Evaluates to a quotation with the same structure as
+ open System
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let ctorInfo =
+ match <@ new System.DateTime(100L) @> with
+ | NewObject(ci, _) -> ci
+ | _ -> failwith "call expected"
+
+ let argExpr = <@ 100000L @>
+
+ Expr.NewObject(ctorInfo, [argExpr])
+
+ Evaluates to a quotation with the same structure as
+ open System
+ open FSharp.Quotations
+
+ let vVar = Var("v", typeof<int>)
+ let vExpr = Expr.Var(vVar)
+
+ Expr.NewDelegate(typeof<Func<int,int>>, [vVar], vExpr)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ Expr.NewArray(typeof<int>, [ <@ 1 @>; <@ 2 @> ])
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let fVar = Var("f", typeof<int -> int>)
+ let gVar = Var("v", typeof<int -> int>)
+ let fExpr = Expr.Var(fVar)
+ let gExpr = Expr.Var(gVar)
+ let fImplExpr = <@ fun x -> (%%gExpr : int -> int) (x - 1) + 1 @>
+ let gImplExpr = <@ fun x -> if x > 0 then (%%fExpr : int -> int) (x - 1) else 0 @>
+ let bodyExpr = <@ (%%gExpr : int -> int) 10 @>
+
+ Expr.LetRecursive([(fVar, fImplExpr); (gVar, gImplExpr)], bodyExpr)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ let vVar = Var("v", typeof<int>)
+ let rhsExpr = <@ 6 @>
+ let vExpr = Expr.Var(vVar)
+
+ Expr.Let(vVar, rhsExpr, vExpr)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let vVar = Var("v", typeof<int>)
+ let vExpr = Expr.Var(vVar)
+
+ Expr.Lambda(vVar, vExpr)
+
+ Evaluates to
+ open FSharp.Quotations
+
+ let guardExpr = <@ 1 > 3 @>
+ let thenExpr = <@ 6 @>
+ let elseExpr = <@ 7 @>
+
+ Expr.IfThenElse(guardExpr, thenExpr, elseExpr)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ let expr1 = Expr.GlobalVar<int>("x")
+ let expr2 = Expr.GlobalVar<int>("x")
+
+ Evaluates
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let sampleQuotation = <@ fun v -> v * v @>
+
+ let v, body =
+ match sampleQuotation with
+ | Lambda(v, body) -> (v, body)
+ | _ -> failwith "unreachable"
+
+ body.GetFreeVars()
+
+ Evaluates to a set containing the single variable for
+ open FSharp.Quotations
+
+ let loopVariable = Var("x", typeof<int>)
+ let startExpr = <@ 6 @>
+ let endExpr = <@ 7 @>
+ let body = <@ System.Console.WriteLine("hello") @>
+
+ Expr.ForIntegerRangeLoop(loopVariable, startExpr, endExpr, body)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let fieldInfo = typeof<int ref>.GetField("contents@")
+ let refValue = ref 3
+ let refExpr = <@ refValue @>
+ let valueExpr = <@ 6 @>
+
+ Expr.FieldSet(refExpr, fieldInfo, valueExpr)
+
+ Evaluates to
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let fieldInfo = typeof<int ref>.GetField("contents@")
+ let refValue = ref 3
+ let refExpr = <@ refValue @>
+
+ Expr.FieldGet(refExpr, fieldInfo)
+
+ Evaluates to
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let fieldInfo = typeof<System.DayOfWeek>.GetField("Monday")
+
+ Expr.FieldGet(fieldInfo)
+
+ Evaluates to
+ open FSharp.Quotations
+
+ Expr.DefaultValue(typeof<int>)
+
+ Evaluates to the quotation
+ open FSharp.Quotations
+
+ let expr = <@ box "3" @>
+
+ Expr.Coerce(expr, typeof<string>)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ let rawExpr = <@ 1 @>
+
+ Expr.Cast<int>(rawExpr)
+
+ Evaluates with type
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ // Get the entrypoint for inline addition that takes an explicit witness
+ let addMethInfoG, addMethInfoGW =
+ match <@ 1+1 @> with
+ | CallWithWitnesses(None, mi, miW, _, _) ->
+ mi.GetGenericMethodDefinition(), miW.GetGenericMethodDefinition()
+ | _ ->
+ failwith "call expected"
+
+ // Make a non-standard witness for addition for a type C
+
+ type C(value: int) =
+ member x.Value = value
+
+ let witnessExpr = <@ (fun (x: C) (y: C) -> C(x.Value + y.Value)) @>
+ let argExpr1 = <@ C(4) @>
+ let argExpr2 = <@ C(5) @>
+
+ // Instantiate the generic method at the right type
+
+ let addMethInfo = addMethInfoG.MakeGenericMethod(typeof<C>, typeof<C>, typeof<C>)
+ let addMethInfoW = addMethInfoGW.MakeGenericMethod(typeof<C>, typeof<C>, typeof<C>)
+
+ Expr.CallWithWitnesses(addMethInfo, addMethInfoW, [witnessExpr], [argExpr1; argExpr2])
+
+ Evaluates to a quotation with the same structure as
+ open System
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let objExpr, methInfo =
+ match <@ Console.Out.WriteLine("1") @> with
+ | Call(Some obj, mi, _) -> obj, mi
+ | _ -> failwith "call expected"
+
+ let argExpr = <@ "Hello World" @>
+
+ Expr.Call(objExpr, methInfo, [argExpr])
+
+ Evaluates to a quotation with the same structure as
+ open System
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let methInfo =
+ match <@ Console.WriteLine("1") @> with
+ | Call(_, mi, _) -> mi
+ | _ -> failwith "call expected"
+
+ let argExpr = <@ "Hello World" @>
+
+ Expr.Call(methInfo, [argExpr])
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ let funcExpr = <@ (fun (x, y) z -> x + y + z) @>
+ let curriedArgExprs = [[ <@ 1 @>; <@ 2 @> ]; [ <@ 3 @> ]]
+
+ Expr.Applications(funcExpr, curriedArgExprs)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ let funcExpr = <@ (fun x -> x + 1) @>
+ let argExpr = <@ 3 @>
+
+ Expr.Application(funcExpr, argExpr)
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+
+ let array = [| 1; 2; 3 |]
+
+ let addrExpr = Expr.AddressOf(<@ array.[1] @>)
+
+ Expr.AddressSet(addrExpr, <@ 4 @>)
+
+ Evaluates to
+ open FSharp.Quotations
+
+ let array = [| 1; 2; 3 |]
+
+ Expr.AddressOf(<@ array.[1] @>)
+
+ Evaluates to
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ match <@ fun v -> v @> with
+ | Lambda(v, body) -> v.Type
+ | _ -> failwith "unreachable"
+
+ Evaluates to
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ match <@ fun v -> v @> with
+ | Lambda(v, body) -> v.Name
+ | _ -> failwith "unreachable"
+
+ Evaluates to
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ match <@ fun v -> v @> with
+ | Lambda(v, body) -> v.IsMutable
+ | _ -> failwith "unreachable"
+
+ Evaluates to
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let valueVar1 = Var.Global("value", typeof<int>)
+ let valueVar2 = Var.Global("value", typeof<int>)
+
+ Evaluates both to
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+
+ let valueVar = Var("value"), typeof<int>)
+
+ Evaluates to a new quotation variable with the given name and type
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+ open FSharp.Quotations.DerivedPatterns
+
+ [<ReflectedDefinition>]
+ type C<'T>() =
+ member x.Count with set (v: int) = ()
+
+ let inpExpr = <@ C<int>().Count <- 3 @>
+
+ let implExpr =
+ match inpExpr with
+ | PropertySet(Some _, PropertySetterWithReflectedDefinition implExpr, [], _valueExpr) -> implExpr
+ | _ -> failwith "unexpected"
+
+ Evaluates
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+ open FSharp.Quotations.DerivedPatterns
+
+ [<ReflectedDefinition>]
+ type C<'T>() =
+ member x.Identity = x
+
+ let inpExpr = <@ C<int>().Identity @>
+
+ let implExpr =
+ match inpExpr with
+ | PropertyGet(Some _, PropertyGetterWithReflectedDefinition implExpr, [ ]) -> implExpr
+ | _ -> failwith "unexpected"
+
+ Evaluates
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+ open FSharp.Quotations.DerivedPatterns
+
+ [<ReflectedDefinition>]
+ let f x = (x, x)
+
+ let inpExpr = <@ f 4 @>
+
+ let implExpr =
+ match inpExpr with
+ | Call(None, MethodWithReflectedDefinition implExpr, [ _argExpr ]) -> implExpr
+ | _ -> failwith "unexpected"
+
+ Evaluates
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+ open FSharp.Quotations.DerivedPatterns
+
+ let inpExpr = <@ Console.WriteLine("hello") @>
+
+ match inpExpr with
+ | SpecificCall <@ Console.WriteLine("1") @> (None, [], [ argExpr ]) -> argExpr
+ | _ -> failwith "unexpected"
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations
+ open FSharp.Quotations.Patterns
+ open FSharp.Quotations.DerivedPatterns
+
+ let (|ConsoleWriteLineOneArg|_|) = (|SpecificCall|_|) <@ Console.WriteLine("1") @>
+
+ let inpExpr = <@ Console.WriteLine("hello") @>
+
+ match inpExpr with
+ | ConsoleWriteLineOneArg (None, [], [ argExpr ]) -> argExpr
+ | _ -> failwith "unexpected"
+
+ Evaluates to a quotation with the same structure as
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 8.0M @> with
+ | Decimal v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 8UL @> with
+ | UInt64 v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 8L @> with
+ | Int64 v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 8u @> with
+ | UInt32 v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 8 @> with
+ | Int32 v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 8us @> with
+ | UInt16 v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 8s @> with
+ | Int16 v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 8uy @> with
+ | Byte v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 8y @> with
+ | SByte v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 'a' @> with
+ | Char v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 1.0 @> with
+ | Double v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ 1.0f @> with
+ | Single v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ "a" @> with
+ | String v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ true @> with
+ | Bool v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ () @> with
+ | Unit v -> v
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ true || false @> with
+ | OrElse (a, b) -> (a, b)
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ true && false @> with
+ | AndAlso (a, b) -> (a, b)
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.Patterns
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ (fun f -> f (1, 2) 3) @> with
+ | Lambda(_, Applications (f, curriedArgs)) ->
+ curriedArgs |> List.map (fun args -> args.Length)
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ open FSharp.Quotations.Patterns
+ open FSharp.Quotations.DerivedPatterns
+
+ match <@ (fun (a1, a2) b -> ()) @> with
+ | Lambdas(curriedVars, _) ->
+ curriedVars |> List.map (List.map (fun arg -> arg.Name))
+ | _ -> failwith "unexpected"
+
+ Evaluates to
+ Async.DefaultCancellationToken.Register(fun () -> printfn "Computation Cancelled") |> ignore
+ let primes = [ 2; 3; 5; 7; 11 ]
+
+ for i in primes do
+ async {
+ do! Async.Sleep(i * 1000)
+ printfn $"{i}"
+ }
+ |> Async.Start
+
+ Thread.Sleep(6000)
+ Async.CancelDefaultToken()
+ printfn "Tasks Finished"
+
+ This will print "2" 2 seconds from start, "3" 3 seconds from start, "5" 5 seconds from start, cease computation and then
+ print "Computation Cancelled", followed by "Tasks Finished".
+
+ let primes = [ 2; 3; 5; 7; 11 ]
+ for i in primes do
+ Async.TryCancelled(
+ async {
+ do! Async.Sleep(i * 1000)
+ printfn $"{i}"
+ },
+ fun oce -> printfn $"Computation Cancelled: {i}")
+ |> Async.Start
+
+ Thread.Sleep(6000)
+ Async.CancelDefaultToken()
+ printfn "Tasks Finished"
+
+ This will print "2" 2 seconds from start, "3" 3 seconds from start, "5" 5 seconds from start, cease computation
+ and then print "Computation Cancelled: 7", "Computation Cancelled: 11" and "Tasks Finished" in any order.
+
+ async {
+ do! Async.SwitchToNewThread()
+ do! someLongRunningComputation()
+ do! Async.SwitchToThreadPool()
+
+ for i in 1 .. 10 do
+ do! someShortRunningComputation()
+ } |> Async.StartImmediate
+
+ This will run someLongRunningComputation() without blocking the threads in the threadpool, and then switch to the
+ threadpool for shorter computations.
+
+ async {
+ do! Async.SwitchToNewThread()
+ do! someLongRunningComputation()
+ } |> Async.StartImmediate
+
+ This will run someLongRunningComputation() without blocking the threads in the threadpool.
+
+ printfn "A"
+
+ let t =
+ async {
+ printfn "B"
+ do! Async.Sleep(1000)
+ printfn "C"
+ } |> Async.StartImmediateAsTask
+
+ printfn "D"
+ t.Wait()
+ printfn "E"
+
+ Prints "A", "B", "D" immediately, then "C", "E" in 1 second.
+
+ printfn "A"
+
+ async {
+ printfn "B"
+ do! Async.Sleep(1000)
+ printfn "C"
+ } |> Async.StartImmediate
+
+ printfn "D"
+
+ Prints "A", "B", "D" immediately, then "C" in 1 second
+
+ async { ...
+ let! completor1 = childComputation1 |> Async.StartChild
+ let! completor2 = childComputation2 |> Async.StartChild
+ ...
+ let! result1 = completor1
+ let! result2 = completor2
+ ... }
+
+
+ When used in this way, each use of
+
+ let computeWithTimeout timeout =
+ async {
+ let! completor1 =
+ Async.StartChild(
+ (async {
+ do! Async.Sleep(1000)
+ return 1
+ }),
+ millisecondsTimeout = timeout)
+
+ let! completor2 =
+ Async.StartChild(
+ (async {
+ do! Async.Sleep(2000)
+ return 2
+ }),
+ millisecondsTimeout = timeout)
+
+ let! v1 = completor1
+ let! v2 = completor2
+ printfn $"Result: {v1 + v2}"
+ } |> Async.RunSynchronously
+
+ Will throw a System.TimeoutException if called with a timeout less than 2000, otherwise will print "Result: 3".
+
+ printfn "A"
+
+ let t =
+ async {
+ printfn "B"
+ do! Async.Sleep(1000)
+ printfn "C"
+ } |> Async.StartAsTask
+
+ printfn "D"
+ t.Wait()
+ printfn "E"
+
+ Prints "A", then "D", "B" quickly in any order, then "C", "E" in 1 second.
+
+ printfn "A"
+
+ async {
+ printfn "B"
+ do! Async.Sleep(1000)
+ printfn "C"
+ } |> Async.Start
+
+ printfn "D"
+
+ Prints "A", then "D", "B" quickly in any order, and then "C" in 1 second.
+
+ async {
+ printfn "A"
+ do! Async.Sleep(TimeSpan(0, 0, 1))
+ printfn "B"
+ } |> Async.Start
+ printfn "C"
+
+ Prints "C", then "A" quickly, and then "B" 1 second later.
+
+ async {
+ printfn "A"
+ do! Async.Sleep(1000)
+ printfn "B"
+ } |> Async.Start
+
+ printfn "C"
+
+ Prints "C" and "A" quickly in any order, and then "B" 1 second later
+
+ let primes = [ 2; 3; 5; 7; 10; 11 ]
+ let computations =
+ [ for i in primes do
+ async {
+ do! Async.Sleep(System.Random().Next(1000, 2000))
+
+ if i % 2 > 0 then
+ printfn $"{i}"
+ return true
+ else
+ return false
+ }
+ ]
+
+ let t =
+ Async.Sequential(computations)
+ |> Async.StartAsTask
+
+ t.Wait()
+ printfn $"%A{t.Result}"
+
+ This will print "3", "5", "7", "11" with ~1-2 seconds between them except for pauses where even numbers would be and then
+ prints [| false; true; true; true; false; true |].
+
+ printfn "A"
+
+ let result = async {
+ printfn "B"
+ do! Async.Sleep(1000)
+ printfn "C"
+ 17
+ } |> Async.RunSynchronously
+
+ printfn "D"
+
+ Prints "A", "B" immediately, then "C", "D" in 1 second. result is set to 17.
+
+ let primes = [ 2; 3; 5; 7; 10; 11 ]
+ let computations =
+ [ for i in primes do
+ async {
+ do! Async.Sleep(System.Random().Next(1000, 2000))
+
+ return
+ if i % 2 > 0 then
+ printfn $"{i}"
+ true
+ else
+ false
+ } ]
+
+ let t =
+ Async.Parallel(computations, maxDegreeOfParallelism=3)
+ |> Async.StartAsTask
+
+ t.Wait()
+ printfn $"%A{t.Result}"
+
+ This will print "3", "5" (in any order) in 1-2 seconds, and then "7", "11" (in any order) in 1-2 more seconds and then
+ [| false; true; true; true; false; true |].
+
+ let primes = [ 2; 3; 5; 7; 10; 11 ]
+ let t =
+ [ for i in primes do
+ async {
+ do! Async.Sleep(System.Random().Next(1000, 2000))
+
+ if i % 2 > 0 then
+ printfn $"{i}"
+ return true
+ else
+ return false
+ }
+ ]
+ |> Async.Parallel
+ |> Async.StartAsTask
+
+ t.Wait()
+ printfn $"%A{t.Result}"
+
+ This will print "3", "5", "7", "11" (in any order) in 1-2 seconds and then [| false; true; true; true; false; true |].
+
+ let primes = [ 2; 3; 5; 7; 11 ]
+ for i in primes do
+ async {
+ use! holder = Async.OnCancel(fun () -> printfn $"Computation Cancelled: {i}")
+ do! Async.Sleep(i * 1000)
+ printfn $"{i}"
+ }
+ |> Async.Start
+
+ Thread.Sleep(6000)
+ Async.CancelDefaultToken()
+ printfn "Tasks Finished"
+
+ This will print "2" 2 seconds from start, "3" 3 seconds from start, "5" 5 seconds from start, cease computation
+ and then print "Computation Cancelled: 7", "Computation Cancelled: 11" and "Tasks Finished" in any order.
+
+ let readFile filename numBytes =
+ async {
+ use file = System.IO.File.OpenRead(filename)
+ printfn "Reading from file %s." filename
+ // Throw away the data being read.
+ do! file.AsyncRead(numBytes) |> Async.Ignore
+ }
+ readFile "example.txt" 42 |> Async.Start
+
+ Reads bytes from a given file asynchronously and then ignores the result, allowing the do! to be used with functions
+ that return an unwanted value.
+
+ let someRiskyBusiness() =
+ match DateTime.Today with
+ | dt when dt.DayOfWeek = DayOfWeek.Monday -> failwith "Not compatible with Mondays"
+ | dt -> dt
+
+ let computation =
+ (fun (successCont, exceptionCont, cancellationCont) ->
+ try
+ someRiskyBusiness () |> successCont
+ with
+ | :? OperationCanceledException as oce -> cancellationCont oce
+ | e -> exceptionCont e)
+ |> Async.FromContinuations
+
+ Async.StartWithContinuations(
+ computation,
+ (fun result -> printfn $"Result: {result}"),
+ (fun e -> printfn $"Exception: {e}"),
+ (fun oce -> printfn $"Cancelled: {oce}")
+ )
+
+ This anonymous function will call someRiskyBusiness() and properly use the provided continuations
+ defined to report the outcome.
+
+ printfn "Starting"
+ let primes = [ 2; 3; 5; 7 ]
+ let computations =
+ [ for i in primes do
+ async {
+ do! Async.Sleep(System.Random().Next(1000, 2000))
+ return if i % 2 > 0 then Some(i) else None
+ }
+ ]
+
+ computations
+ |> Async.Choice
+ |> Async.RunSynchronously
+ |> function
+ | Some (i) -> printfn $"{i}"
+ | None -> printfn "No Result"
+
+ Prints one randomly selected odd number in 1-2 seconds. If the list is changed to all even numbers, it will
+ instead print "No Result".
+
+ let primes = [ 2; 3; 5; 7 ]
+ let computations =
+ [ for i in primes do
+ async {
+ do! Async.Sleep(System.Random().Next(1000, 2000))
+
+ return
+ if i % 2 > 0 then
+ Some(i)
+ else
+ failwith $"Even numbers not supported: {i}"
+ }
+ ]
+
+ computations
+ |> Async.Choice
+ |> Async.RunSynchronously
+ |> function
+ | Some (i) -> printfn $"{i}"
+ | None -> printfn "No Result"
+
+ Will sometimes print one randomly selected odd number, sometimes throw System.Exception("Even numbers not supported: 2").
+
+ let someRiskyBusiness() =
+ match DateTime.Today with
+ | dt when dt.DayOfWeek = DayOfWeek.Monday -> failwith "Not compatible with Mondays"
+ | dt -> dt
+
+ async { return someRiskyBusiness() }
+ |> Async.Catch
+ |> Async.RunSynchronously
+ |> function
+ | Choice1Of2 result -> printfn $"Result: {result}"
+ | Choice2Of2 e -> printfn $"Exception: {e}"
+
+ Prints the returned value of someRiskyBusiness() or the exception if there is one.
+
+ let primes = [ 2; 3; 5; 7; 11 ]
+
+ let computations =
+ [ for i in primes do
+ async {
+ do! Async.Sleep(i * 1000)
+ printfn $"{i}"
+ }
+ ]
+
+ try
+ let t =
+ Async.Parallel(computations, 3) |> Async.StartAsTask
+
+ Thread.Sleep(6000)
+ Async.CancelDefaultToken()
+ printfn $"Tasks Finished: %A{t.Result}"
+ with
+ | :? System.AggregateException as ae -> printfn $"Tasks Not Finished: {ae.Message}"
+
+ This will print "2" 2 seconds from start, "3" 3 seconds from start, "5" 5 seconds from start, cease computation and
+ then print "Tasks Not Finished: One or more errors occurred. (A task was canceled.)".
+
+ open System.Net
+ open System
+ let client = new WebClient()
+ Uri("https://www.w3.com") |> fun x -> client.AsyncDownloadFile(x, "output.html") |> Async.RunSynchronously
+
+ This will download the server response as a file and output it as output.html
+
+ open System.Net
+ open System.Text
+ open System
+ let client = new WebClient()
+ client.AsyncDownloadData(Uri("https://www.w3.org")) |> Async.RunSynchronously |> Encoding.ASCII.GetString
+
+
+ open System
+ let client = new WebClient()
+ Uri("https://www.w3.org") |> client.AsyncDownloadString |> Async.RunSynchronously
+
+ This will download the server response from https://www.w3.org
+
+ open System.Net
+ open System.IO
+ let responseStreamToString = fun (responseStream : WebResponse) ->
+ let reader = new StreamReader(responseStream.GetResponseStream())
+ reader.ReadToEnd()
+ let webRequest = WebRequest.Create("https://www.w3.org")
+ let result = webRequest.AsyncGetResponse() |> Async.RunSynchronously |> responseStreamToString
+
+
+ open System
+
+ let createTimer interval =
+ let timer = new Timers.Timer(interval)
+ timer.AutoReset <- true
+ timer.Enabled <- true
+ timer.Elapsed
+
+ let timer = createTimer 1000
+
+ let pairWise = Event.pairwise timer
+
+ let extractPair (pair: Timers.ElapsedEventArgs * Timers.ElapsedEventArgs) =
+ let leftPair, rightPair = pair
+ printfn $"(Left): {leftPair.SignalTime} (Right): {rightPair.SignalTime}"
+
+ pairWise.Subscribe(extractPair) |> ignore
+
+ Console.ReadLine() |> ignore
+
+ The sample will output the timer event every second:
+ open System
+
+ let createTimer interval =
+ let timer = new Timers.Timer(interval)
+ timer.AutoReset <- true
+ timer.Enabled <- true
+ timer.Elapsed
+
+ let timer = createTimer 1000
+
+ Event.add (fun (event: Timers.ElapsedEventArgs) -> printfn $"{event.SignalTime} ") timer
+
+ Console.ReadLine() |> ignore
+
+ The sample will output the timer event every second:
+ open System
+
+ let createTimer interval =
+ let timer = new Timers.Timer(interval)
+ timer.AutoReset <- true
+ timer.Enabled <- true
+ timer.Elapsed
+
+ let timer = createTimer 1000
+
+ let multiplyBy number =
+ fun (timerEvent: Timers.ElapsedEventArgs) -> number * timerEvent.SignalTime./// Second
+
+ let initialState = 2
+
+ let scan = Event.scan multiplyBy initialState timer
+
+ scan.Subscribe(fun x -> printf "%A " x) |> ignore
+
+ Console.ReadLine() |> ignore
+
+ The sample will output depending on your timestamp. It will multiply the seconds with an initial state of 2:
+ open System
+
+ let createTimer interval =
+ let timer = new Timers.Timer(interval)
+ timer.AutoReset <- true
+ timer.Enabled <- true
+ timer.Elapsed
+
+ let timer = createTimer 1000
+
+ let getEvenSeconds (number: Timers.ElapsedEventArgs) =
+ match number with
+ | _ when number.SignalTime.Second % 2 = 0 -> Some number.SignalTime
+ | _ -> None
+
+ let evenSecondsEvent = Event.choose getEvenSeconds timer
+
+ evenSecondsEvent.Subscribe(fun x -> printfn $"{x} ")
+ |> ignore
+
+ Console.ReadLine() |> ignore
+
+ The sample will output:
+ open System
+
+ let createTimer interval =
+ let timer = new Timers.Timer(interval)
+ timer.AutoReset <- true
+ timer.Enabled <- true
+ timer.Elapsed
+
+ let timer = createTimer 1000
+
+ let bySeconds (timerEvent: Timers.ElapsedEventArgs) =
+ match timerEvent.SignalTime.Second % 2 = 0 with
+ | true -> Choice1Of2 timerEvent.SignalTime.Second
+ | false -> Choice2Of2 $"{timerEvent.SignalTime.Second} is not an even num ber"
+
+ let evenSplit, printOddNumbers = Event.split bySeconds timer
+
+ let printOutput event functionName =
+ Event.add (fun output -> printfn $"{functionName} - Split output: {output}. /// Type: {output.GetType()}") event
+
+ printOutput evenSplit (nameof evenSplit) |> ignore
+
+ printOutput printOddNumbers (nameof printOddNumbers)
+ |> ignore
+
+ Console.ReadLine() |> ignore
+
+ The sample will split the events by even or odd seconds:
+ open System
+
+ let createTimer interval =
+ let timer = new Timers.Timer(interval)
+ timer.AutoReset <- true
+ timer.Enabled <- true
+ timer.Elapsed
+
+ let timer = createTimer 1000
+
+ let getEvenSeconds (number: Timers.ElapsedEventArgs) =
+ match number with
+ | _ when number.SignalTime.Second % 2 = 0 -> true
+ | _ -> false
+
+ let leftPartition, rightPartition = Event.partition getEvenSeconds timer
+
+ leftPartition.Subscribe(fun x -> printfn $"Left partition: {x.SignalTime}")
+ |> ignore
+
+ rightPartition.Subscribe(fun x -> printfn $"Right partition: {x.SignalTime}")
+ |> ignore
+
+ Console.ReadLine() |> ignore
+
+ The sample will partition into two events if it is even or odd seconds:
+ open System
+
+ let createTimer interval =
+ let timer = new Timers.Timer(interval)
+ timer.AutoReset <- true
+ timer.Enabled <- true
+ timer.Elapsed
+
+ let timer = createTimer 1000
+
+ let getEvenSeconds (number: Timers.ElapsedEventArgs) =
+ match number with
+ | _ when number.SignalTime.Second % 2 = 0 -> true
+ | _ -> false
+
+ let evenSecondsEvent = Event.filter getEvenSeconds timer
+
+ evenSecondsEvent.Subscribe(fun x -> printfn $"{x} ")
+ |> ignore
+
+ Console.ReadLine() |> ignore
+
+ The sample will only output even seconds:
+ open System
+
+ let createTimer interval =
+ let timer = new Timers.Timer(interval)
+ timer.AutoReset <- true
+ timer.Enabled <- true
+ timer.Elapsed
+
+ let timer = createTimer 1000
+
+ let transformSeconds (number: Timers.ElapsedEventArgs) =
+ match number with
+ | _ when number.SignalTime.Second % 2 = 0 -> 100
+ | _ -> -500
+
+ let evenSecondsEvent = Event.map transformSeconds timer
+
+ evenSecondsEvent.Subscribe(fun x -> printf $"{x} ")
+ |> ignore
+
+ Console.ReadLine() |> ignore
+
+ The sample will transform the seconds if it's even or odd number and the output is:
+ open System.Reactive.Linq
+ open System
+ let createTimer interval =
+ let timer = new Timers.Timer(interval)
+ timer.AutoReset <- true
+ timer.Enabled <- true
+ timer.Elapsed
+
+ let oneSecondTimer = createTimer 1000
+ let fiveSecondsTimer = createTimer 5000
+
+ let result = Event.merge oneSecondTimer fiveSecondsTimer
+
+ result.Subscribe(fun output -> printfn $"Output - {output.SignalTime} ")
+ |> ignore
+
+ Console.ReadLine() |> ignore
+
+ The sample will output:
+ /// open System.Reactive.Linq
+ let numbers = seq { 1..5 }
+ let observableNumbers = Observable.ToObservable numbers
+
+ let pairWise = Observable.pairwise observableNumbers
+
+ pairWise.Subscribe(fun pair -> printf $"{pair} ")
+ |> ignore
+
+ The sample evaluates to:
+ open System.Reactive.Linq
+ let numbers = seq { 1..3 }
+ let observableNumbers = Observable.ToObservable numbers
+ let printOutput observable =
+ use subscription = Observable.subscribe (fun x -> printfn "%A" x) observable
+ subscription
+ printOutput observableNumbers |> ignore
+
+ The sample evaluates to:
+ open System.Reactive.Linq
+ let numbers = seq { 1..5 }
+ let observableNumbers = Observable.ToObservable numbers
+ let multiplyByTwo = fun number -> printf $"{number * 2} "
+ Observable.add multiplyByTwo observableNumbers
+
+ The sample evaluates to:
+ open System.Reactive.Linq
+ let numbers = seq { 1..5 }
+ let observableNumbers = Observable.ToObservable numbers
+
+ let multiplyBy number = fun y -> number * y
+ let initialState = 2
+ let scan = Observable.scan multiplyBy initialState observableNumbers
+
+ scan.Subscribe(fun x -> printf "%A " x) |> ignore
+
+ The sample evaluates to:
+ open System.Reactive.Linq
+ let numbers = seq { 1..5 }
+ let observableNumbers = Observable.ToObservable numbers
+
+ let getOddNumbers number =
+ match number with
+ | _ when number % 2 = 0 -> None
+ | _ -> Some number
+
+ let map = Observable.choose getOddNumbers observableNumbers
+
+ map.Subscribe(fun x -> printf $"{x} ") |> ignore
+
+ The sample will output:
+ open System.Reactive.Linq
+ let numbers = seq { 1..5 }
+ let observableNumbers = Observable.ToObservable numbers
+
+ let getEvenNumbers number =
+ match number % 2 = 0 with
+ | true -> Choice1Of2 number
+ | false -> Choice2Of2 $"{number} is not an even number"
+
+ let evenSplit, printOddNumbers = Observable.split getEvenNumbers observableNumbers
+
+ let printOutput observable functionName =
+ use subscription =
+ Observable.subscribe
+ (fun output -> printfn $"{functionName} - Split output: {output}. Type: {output.GetType()}")
+ observable
+
+ subscription
+
+ printOutput evenSplit (nameof evenSplit) |> ignore
+ printOutput printOddNumbers (nameof printOddNumbers) |> ignore
+
+ The sample evaluates to:
+ open System.Reactive.Linq
+ let numbers = seq { 1..5 }
+ let observableNumbers = Observable.ToObservable numbers
+
+ let isEvenNumber = fun number -> number % 2 = 0
+
+ let leftPartition, rightPartition =
+ Observable.partition isEvenNumber observableNumbers
+
+ leftPartition.Subscribe(fun x -> printfn $"Left partition: {x}") |> ignore
+
+ rightPartition.Subscribe(fun x -> printfn $"Right partition: {x}") |> ignore
+
+ The sample evaluates to:
+ open System.Reactive.Linq
+ let numbers = seq { 1..5 }
+ let observableNumbers = Observable.ToObservable numbers
+
+ let getEvenNumbers = fun number -> number % 2 = 0
+ let map = Observable.filter multiplyByTwo observableNumbers
+
+ map.Subscribe(fun x -> printf $"{x} ") |> ignore
+
+ The sample will output:
+ open System.Reactive.Linq
+ let numbers = seq { 1..5 }
+ let observableNumbers = Observable.ToObservable numbers
+
+ let multiplyByTwo = fun number -> number * 2
+ let map = Observable.map multiplyByTwo observableNumbers
+
+ map.Subscribe(fun x -> printf $"{x} ") |> ignore
+
+ The sample will output:
+ open System.Reactive.Linq
+ open System
+
+ let createTimer interval =
+ let timer = new Timers.Timer(interval)
+ timer.AutoReset <- true
+ timer.Enabled <- true
+ Observable.Create(fun observer -> timer.Elapsed.Subscribe(observer))
+
+ let observableFirstTimer = createTimer 1000
+ let observableSecondTimer = createTimer 3000
+
+ let result = Observable.merge observableFirstTimer observableSecondTimer
+
+ result.Subscribe(fun output -> printfn $"Output - {output.SignalTime} ")
+ |> ignore
+
+ Console.ReadLine() |> ignore
+
+ The sample will merge all events at a given interval and output it to the stream:
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.char (Nullable<int>()) // evaluates to Nullable<char>()
+ Nullable.char (Nullable<int>(64)) // evaluates to Nullable<char>('@')
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.decimal (Nullable<int>()) // evaluates to Nullable<decimal>()
+ Nullable.decimal (Nullable<int>(3)) // evaluates to Nullable<decimal>(3.0M)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.unativeint (Nullable<int>()) // evaluates to Nullable<unativeint>()
+ Nullable.unativeint (Nullable<int>(3)) // evaluates to Nullable<unativeint>(3un)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.nativeint (Nullable<int>()) // evaluates to Nullable<nativeint>()
+ Nullable.nativeint (Nullable<int>(3)) // evaluates to Nullable<nativeint>(3n)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.double (Nullable<int>()) // evaluates to Nullable<double>()
+ Nullable.double (Nullable<int>(3)) // evaluates to Nullable<double>(3.0)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.single (Nullable<int>()) // evaluates to Nullable<float32>()
+ Nullable.single (Nullable<int>(3)) // evaluates to Nullable<float32>(3.0f)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.float (Nullable<int>()) // evaluates to Nullable<float>()
+ Nullable.float (Nullable<int>(3)) // evaluates to Nullable<float>(3.0)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.float32 (Nullable<int>()) // evaluates to Nullable<float32>()
+ Nullable.float32 (Nullable<int>(3)) // evaluates to Nullable<float32>(3.0f)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.uint64 (Nullable<int>()) // evaluates to Nullable<uint64>()
+ Nullable.uint64 (Nullable<int>(3)) // evaluates to Nullable<uint64>(3UL)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.int64 (Nullable<int>()) // evaluates to Nullable<int64>()
+ Nullable.int64 (Nullable<int>(3)) // evaluates to Nullable<int64>(3L)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.uint32 (Nullable<int>()) // evaluates to Nullable<uint32>()
+ Nullable.uint32 (Nullable<int>(3)) // evaluates to Nullable(3u)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.int32 (Nullable<int64>()) // evaluates to Nullable<int32>()
+ Nullable.int32 (Nullable<int64>(3)) // evaluates to Nullable(3)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.enum<DayOfWeek> (Nullable<int>()) // evaluates to Nullable<uint>()
+ Nullable.enum<DayOfWeek> (Nullable<int>(3)) // evaluates to Nullable<DayOfWeek>(Wednesday)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.uint (Nullable<int>()) // evaluates to Nullable<uint>()
+ Nullable.uint (Nullable<int>(3)) // evaluates to Nullable(3u)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.int (Nullable<int64>()) // evaluates to Nullable<int>()
+ Nullable.int (Nullable<int64>(3)) // evaluates to Nullable(3)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.uint16 (Nullable<int>()) // evaluates to Nullable<uint16>()
+ Nullable.uint16 (Nullable<int>(3)) // evaluates to Nullable(3us)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.int16 (Nullable<int>()) // evaluates to Nullable<int16>()
+ Nullable.int16 (Nullable<int>(3)) // evaluates to Nullable(3s)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.int8 (Nullable<int>()) // evaluates to Nullable<sbyte>()
+ Nullable.int8 (Nullable<int>(3)) // evaluates to Nullable(3y)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.sbyte (Nullable<int>()) // evaluates to Nullable<sbyte>()
+ Nullable.sbyte (Nullable<int>(3)) // evaluates to Nullable(3y)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.uint8 (Nullable<int>()) // evaluates to Nullable<byte>()
+ Nullable.uint8 (Nullable<int>(3)) // evaluates to Nullable(3uy)
+
+
+ open System
+ open FSharp.Linq.NullableOperators
+
+ Nullable.byte (Nullable<int>()) // evaluates to Nullable<byte>()
+ Nullable.byte (Nullable<int>(3)) // evaluates to Nullable(3uy)
+
+
+ open FSharp.Linq.NullableOperators
+
+ Nullable(3) ?<>= 4 // true
+ Nullable(4) ?<>= 4 // false
+ Nullable() ?<> 4 // true
+
+
+ open FSharp.Linq.NullableOperators
+
+ Nullable(3) ?= 4 // false
+ Nullable(4) ?= 4 // true
+ Nullable() ?= 4 // false
+
+
+ open FSharp.Linq.NullableOperators
+
+ Nullable(3) ?< 4 // true
+ Nullable(4) ?< 4 // false
+ Nullable() ?< 4 // false
+
+
+ open FSharp.Linq.NullableOperators
+
+ Nullable(3) ?<= 4 // true
+ Nullable(5) ?<= 4 // false
+ Nullable() ?<= 4 // false
+
+
+ open FSharp.Linq.NullableOperators
+
+ Nullable(3) ?> 4 // false
+ Nullable(5) ?> 4 // true
+ Nullable() ?> 4 // false
+
+
+ open FSharp.Linq.NullableOperators
+
+ Nullable(3) ?>= 4 // false
+ Nullable(4) ?>= 4 // true
+ Nullable() ?>= 4 // false
+
+
+ let mul x y = x * y
+ [<TailCall>]
+ let rec fact n acc =
+ if n = 0
+ then acc
+ else (fact (n - 1) (mul n acc)) + 23 // warning because of the addition after the call to fact
+
+
+ let kv = System.Collections.Generic.KeyValuePair(42, "the answer")
+ match kv with // evaluates to "found it"
+ | KeyValue (42, v) -> "found it"
+ | KeyValue (k, v) -> "keep waiting"
+
+
+ char "A" // evaluates to 'A'
+ char 0x41 // evaluates to 'A'
+ char 65 // evaluates to 'A'
+
+
+ decimal "42.23" // evaluates to 42.23M
+ decimal 0xff // evaluates to 255M
+ decimal -10 // evaluates to -10M
+
+
+ string 'A' // evaluates to "A"
+ string 0xff // evaluates to "255"
+ string -10 // evaluates to "-10"
+
+
+ unativeint 'A' // evaluates to 65un
+ unativeint 0xff // evaluates to 255un
+ unativeint -10 // evaluates to 18446744073709551606un
+
+
+ nativeint 'A' // evaluates to 65n
+ nativeint 0xff // evaluates to 255n
+ nativeint -10 // evaluates to -10n
+
+
+ float 'A' // evaluates to 65.0
+ float 0xff // evaluates to 255.0
+ float -10 // evaluates to -10.0
+
+
+ float32 'A' // evaluates to 65.0f
+ float32 0xff // evaluates to 255.0f
+ float32 -10 // evaluates to -10.0f
+
+
+ uint64 'A' // evaluates to 65UL
+ uint64 0xff // evaluates to 255UL
+ uint64 -10 // evaluates to 18446744073709551606UL
+
+
+ int64 'A' // evaluates to 65L
+ int64 0xff // evaluates to 255L
+ int64 -10 // evaluates to -10L
+
+
+ uint32 'A' // evaluates to 65u
+ uint32 0xff // evaluates to 255u
+ uint32 -10 // evaluates to 4294967286u
+
+
+ int32 'A' // evaluates to 65
+ int32 0xff // evaluates to 255
+ int32 -10 // evaluates to -10
+
+
+ type Color =
+ | Red = 1
+ | Green = 2
+ | Blue = 3
+ let c: Color = enum 3 // c evaluates to Blue
+
+
+ uint 'A' // evaluates to 65u
+ uint 0xff // evaluates to 255u
+ uint -10 // evaluates to 4294967286u
+
+
+ int 'A' // evaluates to 65
+ int 0xff // evaluates to 255
+ int -10 // evaluates to -10
+
+
+ uint16 'A' // evaluates to 65us
+ uint16 0xff // evaluates to 255s
+ uint16 -10 // evaluates to 65526us
+
+
+ int16 'A' // evaluates to 65s
+ int16 0xff // evaluates to 255s
+ int16 -10 // evaluates to -10s
+
+
+ sbyte 'A' // evaluates to 65y
+ sbyte 0xff // evaluates to -1y
+ sbyte -10 // evaluates to -10y
+
+
+ byte 'A' // evaluates to 65uy
+ byte 0xff // evaluates to 255uy
+ byte -10 // evaluates to 246uy
+
+
+ pown 2.0 3 // evaluates to 8.0
+
+
+ 2.0 ** 3 // evaluates to 8.0
+
+
+ truncate 23.92 // evaluates to 23.0
+ truncate 23.92f // evaluates to 23.0f
+
+
+ tanh -1.0 // evaluates to -0.761594156
+ tanh 0.0 // evaluates to 0.0
+ tanh 1.0 // evaluates to 0.761594156
+
+
+ tan (-0.5 * System.Math.PI) // evaluates to -1.633123935e+16
+ tan (0.0 * System.Math.PI) // evaluates to 0.0
+ tan (0.5 * System.Math.PI) // evaluates to 1.633123935e+16
+
+
+ sinh -1.0 // evaluates to -1.175201194
+ sinh 0.0 // evaluates to 0.0
+ sinh 1.0 // evaluates to 1.175201194
+
+
+ sin (0.0 * System.Math.PI) // evaluates to 0.0
+ sin (0.5 * System.Math.PI) // evaluates to 1.0
+ sin (1.0 * System.Math.PI) // evaluates to 1.224646799e-16
+
+
+ cosh -1.0 // evaluates to 1.543080635
+ cosh 0.0 // evaluates to 1.0
+ cosh 1.0 // evaluates to 1.543080635
+
+
+ cos (0.0 * System.Math.PI) // evaluates to 1.0
+ cos (0.5 * System.Math.PI) // evaluates to 6.123233996e-17
+ cos (1.0 * System.Math.PI) // evaluates to -1.0
+
+
+ sqrt 2.0 // Evaluates to 1.414213562
+ sqrt 100.0 // Evaluates to 10.0
+
+
+ log10 1000.0 // Evaluates to 3.0
+ log10 100000.0 // Evaluates to 5.0
+ log10 0.0001 // Evaluates to -4.0
+ log10 -20.0 // Evaluates to nan
+
+
+ let logBase baseNumber value = (log value) / (log baseNumber)
+ logBase 2.0 32.0 // Evaluates to 5.0
+ logBase 10.0 1000.0 // Evaluates to 3.0
+
+
+ round 3.49 // Evaluates to 3.0
+ round -3.49 // Evaluates to -3.0
+ round 3.5 // Evaluates to 4.0
+ round -3.5 // Evaluates to -4.0
+
+
+ sign -12.0 // Evaluates to -1
+ sign 43 // Evaluates to 1
+
+
+ floor 12.1 // Evaluates to 12.0
+ floor -1.9 // Evaluates to -2.0
+
+
+ exp 0.0 // Evaluates to 1.0
+ exp 1.0 // Evaluates to 2.718281828
+ exp -1.0 // Evaluates to 0.3678794412
+ exp 2.0 // Evaluates to 7.389056099
+
+
+ ceil 12.1 // Evaluates to 13.0
+ ceil -1.9 // Evaluates to -1.0
+
+
+ let angleFromPlaneAtXY x y = atan2 y x * 180.0 / System.Math.PI
+ angleFromPlaneAtXY 0.0 -1.0 // Evaluates to -90.0
+ angleFromPlaneAtXY 1.0 1.0 // Evaluates to 45.0
+ angleFromPlaneAtXY -1.0 1.0 // Evaluates to 135.0
+
+
+ let angleFrom opposite adjacent = atan(opposite / adjacent)
+ angleFrom 5.0 5.0 // Evaluates to 0.7853981634
+
+
+ let angleFromOpposite opposite hypotenuse = asin(opposite / hypotenuse)
+ angleFromOpposite 6.0 10.0 // Evaluates to 0.6435011088
+ angleFromOpposite 5.0 3.0 // Evaluates to nan
+
+
+ let angleFromAdjacent adjacent hypotenuse = acos(adjacent / hypotenuse)
+ angleFromAdjacent 8.0 10.0 // Evaluates to 0.6435011088
+
+
+ abs -12 // Evaluates to 12
+ abs -15.0 // Evaluates to 15.0
+
+
+ hash "Bob Jones" // Evaluates to -325251320
+
+
+ sizeof<bool> // Evaluates to 1
+ sizeof<byte> // Evaluates to 1
+ sizeof<int> // Evaluates to 4
+ sizeof<double> // Evaluates to 8
+ sizeof<struct(byte * byte)> // Evaluates to 2
+ sizeof<nativeint> // Evaluates to 4 or 8 (32-bit or 64-bit) depending on your platform
+
+
+ typeof<int list;> // Evaluates to Microsoft.FSharp.Collections.FSharpList`1[System.Int32]
+ typedefof<int list;> // Evaluates to Microsoft.FSharp.Collections.FSharpList`1[T] ///
+
+
+ let myVariableName = "This value doesn't matter"
+ nameof(myVariableName) // Evaluates to "myVariableName"
+
+
+ let t = typeof<int> // Gets the System.Type
+ t.FullName // Evaluates to "System.Int32"
+
+
+ open System.IO
+
+ using (File.AppendText "test.txt") (fun writer ->
+ for i in 1 .. 10 do
+ writer.WriteLine("Hello World {0}", i))
+
+
+
+ open System.Linq
+
+ /// A counter object, supporting unlocked and locked increment
+ type TestCounter () =
+ let mutable count = 0
+
+ /// Increment the counter, unlocked
+ member this.IncrementWithoutLock() =
+ count <- count + 1
+
+ /// Increment the counter, locked
+ member this.IncrementWithLock() =
+ lock this (fun () -> count <- count + 1)
+
+ /// Get the count
+ member this.Count = count
+
+ let counter = TestCounter()
+
+ // Create a parallel sequence to that uses all our CPUs
+ (seq {1..100000}).AsParallel()
+ .ForAll(fun _ -> counter.IncrementWithoutLock())
+
+ // Evaluates to a number between 1-100000, non-deterministically because there is no locking
+ counter.Count
+
+ let counter2 = TestCounter()
+
+ // Create a parallel sequence to that uses all our CPUs
+ (seq {1..100000}).AsParallel()
+ .ForAll(fun _ -> counter2.IncrementWithLock())
+
+ // Evaluates to 100000 deterministically because the increment to the counter object is locked
+ counter2.Count
+
+
+ [1..2..6] // Evaluates to [1; 3; 5]
+ [1.1..0.2..1.5] // Evaluates to [1.1; 1.3; 1.5]
+ ['a'..'e'] // Evaluates to ['a'; 'b'; 'c'; 'd'; 'e']
+
+
+ [1..4] // Evaluates to [1; 2; 3; 4]
+ [1.5..4.4] // Evaluates to [1.5; 2.5; 3.5]
+ ['a'..'d'] // Evaluates to ['a'; 'b'; 'c'; 'd']
+
+ [|1..4|] // Evaluates to an array [|1; 2; 3; 4|]
+ { 1..4 } // Evaluates to a sequence [1; 2; 3; 4])
+
+
+ [<EntryPoint>]
+ let main argv =
+ if argv.Length = 0 then
+ eprintfn "You must provide arguments"
+ exit(-1) // Causes program to quit with an error code
+ printfn "Argument count: %i" argv.Length
+ 0
+
+
+ seq { for i in 0..10 do yield (i, i*i) }
+
+
+ not (2 + 2 = 5) // Evaluates to true
+
+ // not is a function that can be compose with other functions
+ let fileDoesNotExist = System.IO.File.Exists >> not
+
+
+ let l1 = ['a'; 'b'; 'c']
+ let l2 = ['d'; 'e'; 'f']
+ l1 @ l2 // Evalulates to ['a'; 'b'; 'c'; 'd'; 'e'; 'f']
+
+
+ let count = ref 99 // Creates a reference cell object with a mutable Value property
+ incr count // Increments our counter
+ count.Value // Evaluates to 100
+
+
+ let count = ref 99 // Creates a reference cell object with a mutable Value property
+ decr count // Decrements our counter
+ count.Value // Evaluates to 98
+
+
+ let count = ref 12 // Creates a reference cell object with a mutable Value property
+ count.Value // Evaluates to 12
+ !count // Also evaluates to 12 (with shorter syntax)
+
+
+ let count = ref 0 // Creates a reference cell object with a mutable Value property
+ count.Value <- 1 // Updates the value
+ count := 2 // Also updates the value, but with shorter syntax
+ count.Value // Evaluates to 2
+
+
+ let count = ref 0 // Creates a reference cell object with a mutable Value property
+ count.Value // Evaluates to 0
+ count.Value <- 1 // Updates the value
+ count.Value // Evaluates to 1
+
+
+ id 12 // Evaluates to 12
+ id "abc" // Evaluates to "abc"
+
+
+ type FileReader(fileName: string) =
+ let mutable isOpen = false
+ member this.Open() =
+ if isOpen then invalidOp "File is already open"
+ // ... Here we may open the file ...
+ isOpen <- true
+
+ let reader = FileReader("journal.txt")
+ reader.Open() // Executes fine
+ reader.Open() // Throws System.InvalidOperationException: File is already open
+
+
+ let fullName firstName lastName =
+ if isNull firstName then nullArg (nameof(firstName))
+ if isNull lastName then nullArg (nameof(lastName))
+ firstName + " " + lastName
+
+ fullName null "Jones" // Throws System.ArgumentNullException: Value cannot be null. (Parameter 'firstName')
+
+
+ let fullName firstName lastName =
+ if String.IsNullOrWhiteSpace(firstName) then
+ invalidArg (nameof(firstName)) "First name can't be null or blank"
+ if String.IsNullOrWhiteSpace(lastName) then
+ invalidArg (nameof(lastName)) "Last name can't be null or blank"
+ firstName + " " + lastName
+
+ fullName null "Jones"
+
+ Throws
+ let failingFunction() =
+ failwith "Oh no" // Throws an exception
+ true // Never reaches this
+
+ failingFunction() // Throws a System.Exception
+
+
+ isNull null // Evaluates to true
+ isNull "Not null" // Evaluates to false
+
+
+ let x: int = 123
+ let obj1 = box x // obj1 is a generic object type
+ tryUnbox<int> obj1 // Evaluates to Some(123)
+ tryUnbox<double> obj1 // Evaluates to None
+
+
+ let x: int = 123
+ let obj1 = box x // obj1 is a generic object type
+ unbox<int> obj1 // Evaluates to 123 (int)
+ unbox<double> obj1 // Throws System.InvalidCastException
+
+
+ let x: int = 123
+ let obj1 = box x // obj1 is a generic object type
+ unbox<int> obj1 // Evaluates to 123 (int)
+ unbox<double> obj1 // Throws System.InvalidCastException
+
+
+ ignore 55555 // Evaluates to ()
+
+
+ min 1 2 // Evaluates to 1
+ min [1;2;3] [1;2;4] // Evaluates to [1;2;3]
+ min "zoo" "alpha" // Evaluates to "alpha"
+
+
+ max 1 2 // Evaluates to 2
+ max [1;2;3] [1;2;4] // Evaluates to [1;2;4]
+ max "zoo" "alpha" // Evaluates to "zoo"
+
+
+ compare 1 2 // Evaluates to -1
+ compare [1;2;3] [1;2;4] // Evaluates to -1
+ compare 2 2 // Evaluates to 0
+ compare [1;2;3] [1;2;3] // Evaluates to 0
+ compare 2 1 // Evaluates to 1
+ compare [1;2;4] [1;2;3] // Evaluates to 1
+
+
+ snd ("first", 2) // Evaluates to 2
+
+
+ fst ("first", 2) // Evaluates to "first"
+
+
+ let throwException() =
+ raise(Failure("Oh no!!!"))
+ true // Never gets here
+
+ throwException() // Throws a generic Exception class
+
+
+ let readFile (fileName: string) =
+ try
+ File.ReadAllText(fileName)
+ with ex ->
+ eprintfn "Couldn't read %s" fileName
+ reraise()
+
+ readFile "/this-file-doest-exist"
+ // Prints the message to stderr
+ // Throws a System.IO.FileNotFoundException
+
+
+ open System.IO
+ exception FileNotFoundException of string
+
+ let readFile (fileName: string) =
+ if not (File.Exists(fileName)) then
+ raise(FileNotFoundException(fileName))
+ File.ReadAllText(fileName)
+
+ readFile "/this-file-doest-exist"
+
+ When executed, raises a
+ let arg1 = ValueSome(5)
+ defaultValueArg arg1 6 // Evaluates to 5
+ defaultValueArg ValueNone 6 // Evaluates to 6
+
+
+ type Vector(x: double, y: double, ?z: double) =
+ let z = defaultArg z 0.0
+ member this.X = x
+ member this.Y = y
+ member this.Z = z
+
+ let v1 = Vector(1.0, 2.0)
+ v1.Z // Evaluates to 0.
+ let v2 = Vector(1.0, 2.0, 3.0)
+ v2.Z // Evaluates to 3.0
+
+
+ let sum3 x y z = x + y + z
+ sum3 <||| (3, 4, 5) // Evaluates to 12
+
+
+ let sum x y = x + y
+ sum <|| (3, 4) // Evaluates to 7
+
+
+ let doubleIt x = x * 2
+ doubleIt <| 3 // Evaluates to 6
+
+
+ let sum3 x y z = x + y + z
+ (3, 4, 5) |||> sum3 // Evaluates to 12
+
+
+ let sum x y = x + y
+ (3, 4) ||> sum // Evaluates to 7
+
+
+ let doubleIt x = x * 2
+ 3 |> doubleIt // Evaluates to 6
+
+
+ let addOne x = x + 1
+ let doubleIt x = x * 2
+ let doubleThenAdd = addOne << doubleIt
+ doubleThenAdd 3
+
+
+ let addOne x = x + 1
+ let doubleIt x = x * 2
+ let addThenDouble = addOne >> doubleIt
+ addThenDouble 3 // Evaluates to 8
+
+
+ 5 <> 5 // Evaluates to false
+ 5 <> 6 // Evaluates to true
+ [1; 2] <> [1; 2] // Evaluates to false
+
+
+ 5 = 5 // Evaluates to true
+ 5 = 6 // Evaluates to false
+ [1; 2] = [1; 2] // Evaluates to true
+ (1, 5) = (1, 6) // Evaluates to false
+
+
+ 5 <= 1 // Evaluates to false
+ 5 <= 5 // Evaluates to true
+ [1; 5] <= [1; 6] // Evaluates to true
+
+
+ 5 >= 1 // Evaluates to true
+ 5 >= 5 // Evaluates to true
+ [1; 5] >= [1; 6] // Evaluates to false
+
+
+ 5 > 1 // Evaluates to true
+ 5 > 5 // Evaluates to false
+ (1, "a") > (1, "z") // Evaluates to false
+
+
+ 1 < 5 // Evaluates to true
+ 5 < 5 // Evaluates to false
+ (1, "a") < (1, "z") // Evaluates to true
+
+
+ let byte1 = 60uy // 00111100
+ let byte2 = ~~~b1 // 11000011
+
+ Evaluates to 195
+
+ let a = 206 // 00000000000000000000000011010000
+ let c1 = a >>> 2 // 00000000000000000000000000110100
+ // Evaluates to 51
+ let c2 = a >>> 6 // 00000000000000000000000000000011
+ Evaluates to 3
+
+
+ let a = 13 // 00000000000000000000000000001101
+ let c = a <<< 4 // 00000000000000000000000011010000
+
+ Evaluates to 208
+
+ let a = 13 // 00000000000000000000000000001101
+ let b = 11 // 00000000000000000000000000001011
+ let c = a ^^^ b // 00000000000000000000000000000110
+
+ Evaluates to 6
+
+ let a = 13 // 00000000000000000000000000001101
+ let b = 11 // 00000000000000000000000000001011
+ let c = a ||| b // 00000000000000000000000000001111
+
+ Evaluates to 15
+
+ let a = 13 // 00000000000000000000000000001101
+ let b = 11 // 00000000000000000000000000001011
+ let c = a &&& b // 00000000000000000000000000001001
+
+ Evaluates to 9
+
+ 29 % 5 // Evaluates to 4
+
+
+ 16 / 2 // Evaluates to 8
+
+
+ 8 * 6 // Evaluates to 48
+
+
+ 10 - 2 // Evaluates to 8
+
+
+ 2 + 2 // Evaluates to 4
+ "Hello " + "Word" // Evaluates to "Hello World"
+
+
+ (ValueNone: string ValueOption) |> ValueOption.toObj // evaluates to null
+ ValueSome "not a null string" |> ValueOption.toObj // evaluates to "not a null string"
+
+
+ (null: string) |> ValueOption.ofObj // evaluates to ValueNone
+ "not a null string" |> ValueOption.ofObj // evaluates to (ValueSome "not a null string")
+
+
+ System.Nullable<int>() |> ValueOption.ofNullable // evaluates to ValueNone
+ System.Nullable(42) |> ValueOption.ofNullable // evaluates to ValueSome 42
+
+
+ (ValueNone: int ValueOption) |> ValueOption.toNullable // evaluates to new System.Nullable<int>()
+ ValueSome 42 |> ValueOption.toNullable // evaluates to new System.Nullable(42)
+
+
+ (ValueNone: int ValueOption) |> ValueOption.toList // evaluates to []
+ ValueSome 42 |> ValueOption.toList // evaluates to [42]
+
+
+ (ValueNone: int ValueOption) |> ValueOption.toArray // evaluates to [||]
+ ValueSome 42 |> ValueOption.toArray // evaluates to [|42|]
+
+
+ ValueNone |> ValueOption.filter (fun x -> x >= 5) // evaluates to ValueNone
+ ValueSome 42 |> ValueOption.filter (fun x -> x >= 5) // evaluates to ValueSome 42
+ ValueSome 4 |> ValueOption.filter (fun x -> x >= 5) // evaluates to ValueNone
+
+
+ (ValueNone: int ValueOption ValueOption) |> ValueOption.flatten // evaluates to ValueNone
+ (ValueSome ((ValueNone: int ValueOption))) |> ValueOption.flatten // evaluates to ValueNone
+ (ValueSome (ValueSome 42)) |> ValueOption.flatten // evaluates to ValueSome 42
+
+
+ let tryParse input =
+ match System.Int32.TryParse (input: string) with
+ | true, v -> ValueSome v
+ | false, _ -> ValueNone
+ ValueNone |> ValueOption.bind tryParse // evaluates to ValueNone
+ ValueSome "42" |> ValueOption.bind tryParse // evaluates to ValueSome 42
+ ValueSome "Forty-two" |> ValueOption.bind tryParse // evaluates to ValueNone
+
+
+ (ValueNone, ValueNone, ValueNone) |||> ValueOption.map3 (fun x y z -> x + y + z) // evaluates to ValueNone
+ (ValueSome 100, ValueNone, ValueNone) |||> ValueOption.map3 (fun x y z -> x + y + z) // evaluates to ValueNone
+ (ValueNone, ValueSome 100, ValueNone) |||> ValueOption.map3 (fun x y z -> x + y + z) // evaluates to ValueNone
+ (ValueNone, ValueNone, ValueSome 100) |||> ValueOption.map3 (fun x y z -> x + y + z) // evaluates to ValueNone
+ (ValueSome 5, ValueSome 100, ValueSome 10) |||> ValueOption.map3 (fun x y z -> x + y + z) // evaluates to ValueSome 115
+
+
+ (ValueNone, ValueNone) ||> ValueOption.map2 (fun x y -> x + y) // evaluates to ValueNone
+ (ValueSome 5, ValueNone) ||> ValueOption.map2 (fun x y -> x + y) // evaluates to ValueNone
+ (ValueNone, ValueSome 10) ||> ValueOption.map2 (fun x y -> x + y) // evaluates to ValueNone
+ (ValueSome 5, ValueSome 10) ||> ValueOption.map2 (fun x y -> x + y) // evaluates to ValueSome 15
+
+
+ ValueNone |> ValueOption.map (fun x -> x * 2) // evaluates to ValueNone
+ ValueSome 42 |> ValueOption.map (fun x -> x * 2) // evaluates to ValueSome 84
+
+
+ ValueNone |> ValueOption.iter (printfn "%s") // does nothing
+ ValueSome "Hello world" |> ValueOption.iter (printfn "%s") // prints "Hello world"
+
+
+ (99, ValueNone) ||> ValueOption.contains // evaluates to false
+ (99, ValueSome 99) ||> ValueOption.contains // evaluates to true
+ (99, ValueSome 100) ||> ValueOption.contains // evaluates to false
+
+
+ ValueNone |> ValueOption.forall (fun x -> x >= 5) // evaluates to true
+ ValueSome 42 |> ValueOption.forall (fun x -> x >= 5) // evaluates to true
+ ValueSome 4 |> ValueOption.forall (fun x -> x >= 5) // evaluates to false
+
+
+ ValueNone |> ValueOption.exists (fun x -> x >= 5) // evaluates to false
+ ValueSome 42 |> ValueOption.exists (fun x -> x >= 5) // evaluates to true
+ ValueSome 4 |> ValueOption.exists (fun x -> x >= 5) // evaluates to false
+
+
+ (ValueNone, 0) ||> ValueOption.foldBack (fun x accum -> accum + x * 2) // evaluates to 0
+ (ValueSome 1, 0) ||> ValueOption.foldBack (fun x accum -> accum + x * 2) // evaluates to 2
+ (ValueSome 1, 10) ||> ValueOption.foldBack (fun x accum -> accum + x * 2) // evaluates to 12
+
+
+ (0, ValueNone) ||> ValueOption.fold (fun accum x -> accum + x * 2) // evaluates to 0
+ (0, ValueSome 1) ||> ValueOption.fold (fun accum x -> accum + x * 2) // evaluates to 2
+ (10, ValueSome 1) ||> ValueOption.fold (fun accum x -> accum + x * 2) // evaluates to 12
+
+
+ ValueNone |> ValueOption.count // evaluates to 0
+ ValueSome 99 |> ValueOption.count // evaluates to 1
+
+
+ ValueSome 42 |> ValueOption.get // evaluates to 42
+ (ValueNone: int ValueOption) |> ValueOption.get // throws exception!
+
+
+ (ValueNone: int ValueOption) |> ValueOption.orElseWith (fun () -> ValueNone) // evaluates to ValueNone
+ ValueNone |> ValueOption.orElseWith (fun () -> (ValueSome 99)) // evaluates to ValueSome 99
+ ValueSome 42 |> ValueOption.orElseWith (fun () -> ValueNone) // evaluates to ValueSome 42
+ ValueSome 42 |> ValueOption.orElseWith (fun () -> (ValueSome 99)) // evaluates to ValueSome 42
+
+
+ ((ValueNone: int ValueOption), ValueNone) ||> ValueOption.orElse // evaluates to ValueNone
+ (ValueSome 99, ValueNone) ||> ValueOption.orElse // evaluates to ValueSome 99
+ (ValueNone, ValueSome 42) ||> ValueOption.orElse // evaluates to ValueSome 42
+ (ValueSome 99, ValueSome 42) ||> ValueOption.orElse // evaluates to ValueSome 42
+
+
+ ValueNone |> ValueOption.defaultWith (fun () -> 99) // evaluates to 99
+ ValueSome 42 |> ValueOption.defaultWith (fun () -> 99) // evaluates to 42
+
+
+ (99, ValueNone) ||> ValueOption.defaultValue // evaluates to 99
+ (99, ValueSome 42) ||> ValueOption.defaultValue // evaluates to 42
+
+
+ ValueNone |> ValueOption.isNone // evaluates to true
+ ValueSome 42 |> ValueOption.isNone // evaluates to false
+
+
+ ValueNone |> ValueOption.isSome // evaluates to false
+ ValueSome 42 |> ValueOption.isSome // evaluates to true
+
+
+ (None: string option) |> Option.toObj // evaluates to null
+ Some "not a null string" |> Option.toObj // evaluates to "not a null string"
+
+
+ (null: string) |> Option.ofObj // evaluates to None
+ "not a null string" |> Option.ofObj // evaluates to (Some "not a null string")
+
+
+ System.Nullable<int>() |> Option.ofNullable // evaluates to None
+ System.Nullable(42) |> Option.ofNullable // evaluates to Some 42
+
+
+ (None: int option) |> Option.toNullable // evaluates to new System.Nullable<int>()
+ Some 42 |> Option.toNullable // evaluates to new System.Nullable(42)
+
+
+ (None: int option) |> Option.toList // evaluates to []
+ Some 42 |> Option.toList // evaluates to [42]
+
+
+ (None: int option) |> Option.toArray // evaluates to [||]
+ Some 42 |> Option.toArray // evaluates to [|42|]
+
+
+ None |> Option.filter (fun x -> x >= 5) // evaluates to None
+ Some 42 |> Option.filter (fun x -> x >= 5) // evaluates to Some 42
+ Some 4 |> Option.filter (fun x -> x >= 5) // evaluates to None
+
+
+ (None: int option option) |> Option.flatten // evaluates to None
+ (Some ((None: int option))) |> Option.flatten // evaluates to None
+ (Some (Some 42)) |> Option.flatten // evaluates to Some 42
+
+
+ let tryParse (input: string) =
+ match System.Int32.TryParse input with
+ | true, v -> Some v
+ | false, _ -> None
+ None |> Option.bind tryParse // evaluates to None
+ Some "42" |> Option.bind tryParse // evaluates to Some 42
+ Some "Forty-two" |> Option.bind tryParse // evaluates to None
+
+
+ (None, None, None) |||> Option.map3 (fun x y z -> x + y + z) // evaluates to None
+ (Some 100, None, None) |||> Option.map3 (fun x y z -> x + y + z) // evaluates to None
+ (None, Some 100, None) |||> Option.map3 (fun x y z -> x + y + z) // evaluates to None
+ (None, None, Some 100) |||> Option.map3 (fun x y z -> x + y + z) // evaluates to None
+ (Some 5, Some 100, Some 10) |||> Option.map3 (fun x y z -> x + y + z) // evaluates to Some 115
+
+
+ (None, None) ||> Option.map2 (fun x y -> x + y) // evaluates to None
+ (Some 5, None) ||> Option.map2 (fun x y -> x + y) // evaluates to None
+ (None, Some 10) ||> Option.map2 (fun x y -> x + y) // evaluates to None
+ (Some 5, Some 10) ||> Option.map2 (fun x y -> x + y) // evaluates to Some 15
+
+
+ None |> Option.map (fun x -> x * 2) // evaluates to None
+ Some 42 |> Option.map (fun x -> x * 2) // evaluates to Some 84
+
+
+ None |> Option.iter (printfn "%s") // does nothing
+ Some "Hello world" |> Option.iter (printfn "%s") // prints "Hello world"
+
+
+ (99, None) ||> Option.contains // evaluates to false
+ (99, Some 99) ||> Option.contains // evaluates to true
+ (99, Some 100) ||> Option.contains // evaluates to false
+
+
+ None |> Option.forall (fun x -> x >= 5) // evaluates to true
+ Some 42 |> Option.forall (fun x -> x >= 5) // evaluates to true
+ Some 4 |> Option.forall (fun x -> x >= 5) // evaluates to false
+
+
+ None |> Option.exists (fun x -> x >= 5) // evaluates to false
+ Some 42 |> Option.exists (fun x -> x >= 5) // evaluates to true
+ Some 4 |> Option.exists (fun x -> x >= 5) // evaluates to false
+
+
+ (None, 0) ||> Option.foldBack (fun x accum -> accum + x * 2) // evaluates to 0
+ (Some 1, 0) ||> Option.foldBack (fun x accum -> accum + x * 2) // evaluates to 2
+ (Some 1, 10) ||> Option.foldBack (fun x accum -> accum + x * 2) // evaluates to 12
+
+
+ (0, None) ||> Option.fold (fun accum x -> accum + x * 2) // evaluates to 0
+ (0, Some 1) ||> Option.fold (fun accum x -> accum + x * 2) // evaluates to 2
+ (10, Some 1) ||> Option.fold (fun accum x -> accum + x * 2) // evaluates to 12
+
+
+ None |> Option.count // evaluates to 0
+ Some 99 |> Option.count // evaluates to 1
+
+
+ Some 42 |> Option.get // evaluates to 42
+ (None: int option) |> Option.get // throws exception!
+
+
+ (None: int Option) |> Option.orElseWith (fun () -> None) // evaluates to None
+ None |> Option.orElseWith (fun () -> (Some 99)) // evaluates to Some 99
+ Some 42 |> Option.orElseWith (fun () -> None) // evaluates to Some 42
+ Some 42 |> Option.orElseWith (fun () -> (Some 99)) // evaluates to Some 42
+
+
+ ((None: int Option), None) ||> Option.orElse // evaluates to None
+ (Some 99, None) ||> Option.orElse // evaluates to Some 99
+ (None, Some 42) ||> Option.orElse // evaluates to Some 42
+ (Some 99, Some 42) ||> Option.orElse // evaluates to Some 42
+
+
+ None |> Option.defaultWith (fun () -> 99) // evaluates to 99
+ Some 42 |> Option.defaultWith (fun () -> 99) // evaluates to 42
+
+
+ (99, None) ||> Option.defaultValue // evaluates to 99
+ (99, Some 42) ||> Option.defaultValue // evaluates to 42
+
+
+ None |> Option.isNone // evaluates to true
+ Some 42 |> Option.isNone // evaluates to false
+
+
+ None |> Option.isSome // evaluates to false
+ Some 42 |> Option.isSome // evaluates to true
+
+
+ Error 42 |> Result.toOption // evaluates to ValueNone
+ Ok 42 |> Result.toOption // evaluates to ValueSome 42
+
+
+ Error 42 |> Result.toOption // evaluates to None
+ Ok 42 |> Result.toOption // evaluates to Some 42
+
+
+ Error 42 |> Result.toList // evaluates to []
+ Ok 42 |> Result.toList // evaluates to [ 42 ]
+
+
+ Error 42 |> Result.toArray // evaluates to [||]
+ Ok 42 |> Result.toArray // evaluates to [| 42 |]
+
+
+ Error "Hello world" |> Result.iter (printfn "%s") // does nothing
+ Ok "Hello world" |> Result.iter (printfn "%s") // prints "Hello world"
+
+
+ (99, Error 99) ||> Result.contains // evaluates to false
+ (99, Ok 99) ||> Result.contains // evaluates to true
+ (99, Ok 100) ||> Result.contains // evaluates to false
+
+
+ Error 1 |> Result.forall (fun x -> x >= 5) // evaluates to true
+ Ok 42 |> Result.forall (fun x -> x >= 5) // evaluates to true
+ Ok 4 |> Result.forall (fun x -> x >= 5) // evaluates to false
+
+
+ Error 6 |> Result.exists (fun x -> x >= 5) // evaluates to false
+ Ok 42 |> Result.exists (fun x -> x >= 5) // evaluates to true
+ Ok 4 |> Result.exists (fun x -> x >= 5) // evaluates to false
+
+
+ (Error 2, 0) ||> Result.foldBack (fun x accum -> accum + x * 2) // evaluates to 0
+ (Ok 1, 0) ||> Result.foldBack (fun x accum -> accum + x * 2) // evaluates to 2
+ (Ok 1, 10) ||> Result.foldBack (fun x accum -> accum + x * 2) // evaluates to 12
+
+
+ (0, Error 2) ||> Result.fold (fun accum x -> accum + x * 2) // evaluates to 0
+ (0, Ok 1) ||> Result.fold (fun accum x -> accum + x * 2) // evaluates to 2
+ (10, Ok 1) ||> Result.fold (fun accum x -> accum + x * 2) // evaluates to 12
+
+
+ Error 99 |> Result.count // evaluates to 0
+ Ok 99 |> Result.count // evaluates to 1
+
+
+ Ok 1 |> Result.defaultWith (fun error -> 99) // evaluates to 1
+ Error 2 |> Result.defaultWith (fun error -> 99) // evaluates to 99
+
+
+ Result.defaultValue 2 (Error 3) // evaluates to 2
+ Result.defaultValue 2 (Ok 1) // evaluates to 1
+
+
+ Ok 42 |> Result.isError // evaluates to false
+ Error 42 |> Result.isError // evaluates to true
+
+
+ Ok 42 |> Result.isOk // evaluates to true
+ Error 42 |> Result.isOk // evaluates to false
+
+
+ let tryParse (input: string) =
+ match System.Int32.TryParse input with
+ | true, v -> Ok v
+ | false, _ -> Error "couldn't parse"
+
+ Error "message" |> Result.bind tryParse // evaluates to Error "message"
+
+ Ok "42" |> Result.bind tryParse // evaluates to Ok 42
+
+ Ok "Forty-two" |> Result.bind tryParse // evaluates to Error "couldn't parse"
+
+
+ Ok 1 |> Result.mapError (fun x -> "bar") // evaluates to Ok 1
+
+ Error "foo" |> Result.mapError (fun x -> "bar") // evaluates to Error "bar"
+
+
+ Ok 1 |> Result.map (fun x -> "perfect") // evaluates to Ok "perfect"
+
+ Error "message" |> Result.map (fun x -> "perfect") // evaluates to Error "message"
+
+
+ "Do it!" |> String.replicate 3
+
+ Evaluates to
+ input |> String.mapi (fun i c -> (i, c))
+
+ Evaluates to
+ open System
+
+ let input = "Hello there!"
+
+ input |> String.map Char.ToUpper // evaluates "HELLO THERE!"
+
+
+ String.length null // evaluates 0
+ String.length "" // evaluates 0
+ String.length "123" // evaluates 3
+
+
+ let input = "Hello"
+ input |> String.iteri (fun i c -> printfn "%d. %c %d" (i + 1) c (int c))
+
+ The sample evaluates as
+ 1. H 72
+ 2. e 101
+ 3. l 108
+ 4. l 108
+ 5. o 111
+
+
+ let input = "Hello"
+ input |> String.iter (fun c -> printfn "%c %d" c (int c))
+
+ The sample evaluates as
+ H 72
+ e 101
+ l 108
+ l 108
+ o 111
+
+
+ String.init 10 (fun i -> int '0' + i |> sprintf "%d ")
+
+ The sample evaluates to:
+ open System
+
+ "all are lower" |> String.forall Char.IsLower // evaluates false
+
+ "allarelower" |> String.forall Char.IsLower // evaluates true
+
+
+ open System
+
+ let input = "0 1 2 3 4 5 6 7 8 9 a A m M"
+
+ input |> String.filter Uri.IsHexDigit // evaluates "123456789aA"
+
+
+ open System
+
+ "hello" |> String.filter Char.IsDigit // evaluates ""
+
+
+ open System
+
+ "Yoda" |> String.exists Char.IsUpper // evaluates true
+
+ "nope" |> String.exists Char.IsUpper // evaluates false
+
+
+ let input1 = ["Stefan"; "says:"; "Hello"; "there!"]
+
+ input1 |> String.concat " " // evaluates "Stefan says: Hello there!"
+
+ let input2 = [0..9] |> List.map string
+
+ input2 |> String.concat "" // evaluates "0123456789"
+ input2 |> String.concat ", " // evaluates "0, 1, 2, 3, 4, 5, 6, 7, 8, 9"
+
+ let input3 = ["No comma"]
+
+ input3 |> String.concat "," // evaluates "No comma"
+
+
+ let input = "Stefan says: Hi!"
+
+ input |> String.collect (sprintf "%c ")
+
+ The sample evaluates to
+ "Secret" |> String.collect (fun chr -> int chr |> sprintf "%d ")
+
+ The sample evaluates to
+ failwithf "That's wrong. Five = %d and six = %d" (3+2) (3+3)
+
+ Throws
+ open Printf
+
+ ksprintf (fun s -> s + ", done!") $"Write three = {1+2}"
+
+ Evaluates to
+ open Printf
+
+ kprintf (fun s -> s + ", done!") $"Write three = {1+2}"
+
+ Evaluates to
+ open Printf
+ open System.IO
+
+ let file = File.CreateText("out.txt")
+
+ kfprintf (fun () -> file.Close()) file $"Write three = {1+2}"
+
+ Writes
+ open Printf
+ open System.Text
+
+ let buffer = new StringBuilder()
+
+ kbprintf (fun () -> buffer.ToString()) buffer "Write five = %d" (3+2)
+
+ Evaluates to
+ sprintf "Write five = %d and six = %d" (3+2) (3+3)
+
+ Evaluates to
+ printfn $"Write three = {1+2}"
+ printfn $"Write four = {2+2}"
+
+ After evaluation the two lines are written to
+ printfn "Write five = %d" (3+2)
+ printfn "Write six = %d" (3+3)
+
+ After evaluation the two lines are written to
+ printf $"Write three = {1+2}"
+
+ After evaluation the text
+ printf "Write five = %d" (3+2)
+
+ After evaluation the text
+ eprintfn $"Write three = {1+2}"
+ eprintfn $"Write four = {2+2}"
+
+ After evaluation two lines are written to
+ eprintfn "Write five = %d" (3+2)
+ eprintfn "Write six = %d" (3+3)
+
+ After evaluation two lines are written to
+ eprintf $"Write three = {1+2}"
+
+ After evaluation the text
+ eprintf "Write five = %d" (3+2)
+
+ After evaluation the text
+ open Printf
+ open System.IO
+
+ let file = File.CreateText("out.txt")
+
+ fprintfn file $"Write three = {1+2}"
+ fprintfn file $"Write four = {2+2}"
+ file.Close()
+
+ After evaluation the file contains two lines.
+
+ open Printf
+ open System.IO
+
+ let file = File.CreateText("out.txt")
+
+ fprintfn file "Write five = %d" (3+2)
+ fprintfn file "Write six = %d" (3+3)
+ file.Close()
+
+ After evaluation the file contains two lines.
+
+ open Printf
+ open System.IO
+
+ let file = File.CreateText("out.txt")
+
+ fprintf file $"Write three = {1+2}"
+ file.Close()
+
+ After evaluation the file contains the text
+ open Printf
+ open System.IO
+
+ let file = File.CreateText("out.txt")
+
+ fprintf file "Write five = %d" (3+2)
+ file.Close()
+
+ After evaluation the file contains the text
+ open Printf
+ open System.Text
+
+ let buffer = new StringBuilder()
+
+ bprintf buffer $"Write three = {1+2}"
+ buffer.ToString()
+
+ Evaluates to
+ open Printf
+ open System.Text
+
+ let buffer = new StringBuilder()
+
+ bprintf buffer "Write five = %d" (3+2)
+ buffer.ToString()
+
+ Evaluates to
+ type OverloadsWithSrtp() =
+ [<NoEagerConstraintApplicationAttribute>]
+ static member inline SomeMethod< ^T when ^T : (member Number: int) > (x: ^T, f: ^T -> int) = 1
+ static member SomeMethod(x: 'T list, f: 'T list -> int) = 2
+
+ let inline f x =
+ OverloadsWithSrtp.SomeMethod (x, (fun a -> 1))
+
+ With the attribute, the overload resolution fails, because both members are applicable.
+ Without the attribute, the overload resolution succeeds, because the member constraint is
+ eagerly applied, making the second member non-applicable.
+
+ let findEvensAndSortAndDouble(xs: System.Linq.IQueryable<int>) =
+ query {
+ for x in xs do
+ where (x % 2 = 0)
+ sortBy x
+ select (x+x)
+ }
+
+ let data = [1; 2; 6; 7; 3; 6; 2; 1]
+
+ findEvensAndSortAndDouble (data.AsQueryable()) |> Seq.toList
+
+ Evaluates to
+ let f (Lazy v) = v + v
+
+ let v = lazy (printf "eval!"; 5+5)
+
+ f v
+ f v
+
+ Evaluates to
+ let f v = <@@ (%%v: int) + (%%v: int) @@>
+
+ f <@@ 5 + 5 @@>;;
+
+ Evaluates to an untyped quotation equivalent to
+ let f v = <@ %v + %v @>
+
+ f <@ 5 + 5 @>;;
+
+ Evaluates to a quotation equivalent to
+ array2D [ [ 1.0; 2.0 ]; [ 3.0; 4.0 ] ]
+
+ Evaluates to a 2x2 zero-based array with contents
+ let table = readOnlyDict [ (1, 100); (2, 200) ]
+
+ table[1]
+
+ Evaluates to
+ let table = readOnlyDict [ (1, 100); (2, 200) ]
+
+ table[3]
+
+ Throws
+ let table = dict [ (1, 100); (2, 200) ]
+
+ table[1]
+
+ Evaluates to
+ let table = dict [ (1, 100); (2, 200) ]
+
+ table[3]
+
+ Throws
+ int8 -12
+
+ Evaluates to
+ int8 "3"
+
+ Evaluates to
+ uint8 12
+
+ Evaluates to
+ double 45
+
+ Evaluates to
+ double 12.3f
+
+ Evaluates to
+ single 45
+
+ Evaluates to
+ let sleepExample() =
+ async {
+ printfn "sleeping"
+ do! Async.Sleep 10
+ printfn "waking up"
+ return 6
+ }
+
+ sleepExample() |> Async.RunSynchronously
+
+
+ let values = set [ 1; 2; 3; 5; 7; 11 ]
+
+ Evaluates to a set containing the given numbers.
+
+ Checked.int8 -12
+
+ Evaluates to
+ Checked.int8 "129"
+
+ Throws
+ Checked.uint8 12
+
+ Evaluates to
+ Checked.uint8 -12
+
+ Throws 0
), some non-empty buffer is returned.
+ 0
), some non-empty buffer is returned.
+
+ var (k,v) = kvp;
+
+
+ int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ;
+ int lastElement = someArray[^1]; // lastElement = 5
+
+
+ int[] someArray = new int[5] { 1, 2, 3, 4, 5 };
+ int[] subArray1 = someArray[0..2]; // { 1, 2 }
+ int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
+
+
+ using var array = PooledArrayBuilder<T>.Empty;
+
+ // Using the 'Unsafe.AsRef' method
+ Method(ref Unsafe.AsRef(in builder));
+
+ // Using this helper method
+ Method(ref builder.AsRef());
+
+
+