Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docsrc/tools/doclib.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module DocLib
// Copyright 2010 Steffen Forkmann
// Apache license


#nowarn "49"
open System.IO

module String =
Expand Down
132 changes: 69 additions & 63 deletions src/FSharpPlus/Extensions/Array.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ module Array =
/// <param name="value">The element to add</param>
/// <param name="array">The array to add to</param>
/// <returns>A new array with the element added to the beginning.</returns>
let cons value array =
raiseIfNull (nameof(array)) array
let cons value (array: 'T []) =
let array = nullArgCheck (nameof array) array
Array.insertAt 0 value array

/// <summary>Splits the array in head and tail.</summary>
/// <param name="array">The input array.</param>
/// <returns>A tuple with the head and the tail of the original array.</returns>
/// <exception cref="T:System.ArgumentException">Thrown when the input array is empty.</exception>
let uncons array =
raiseIfNull (nameof(array)) array
if Array.isEmpty array then invalidArg (nameof(array)) LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
let uncons (array: 'T []) =
let array = nullArgCheck (nameof array) array
if Array.isEmpty array then invalidArg (nameof array) LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
else array[0], array[1..]

/// <summary>Applies an array of functions to an array of values and concatenates them.</summary>
Expand All @@ -38,42 +38,48 @@ module Array =
/// val it : int [] = [|2; 4; 6; 3; 6; 9|]
/// </code>
/// </example>
let apply f x =
raiseIfNull (nameof(x)) x
let apply (f: ('T -> 'U) []) (x: 'T []) : 'U [] =
let x = nullArgCheck (nameof x) x

let lenf, lenx = Array.length f, Array.length x
Array.init (lenf * lenx) (fun i -> let (d, r) = Math.DivRem (i, lenx) in f.[d] x.[r])

/// Combines all values from the first array with the second, using the supplied mapping function.
let lift2 f x y =
raiseIfNull (nameof(x)) x
raiseIfNull (nameof(y)) y
/// <summary>Combines all values from three arrays and calls a mapping function on this combination.</summary>
/// <param name="mapping">Mapping function taking three element combination as input.</param>
/// <param name="array1">First array.</param>
/// <param name="array2">Second array.</param>
///
/// <returns>Array with values returned from mapping function.</returns>
let lift2 (mapping: 'T1 -> 'T2 -> 'U) (array1: 'T1 []) (array2: 'T2 []) : 'U [] =
let array1 = nullArgCheck (nameof array1) array1
let array2 = nullArgCheck (nameof array2) array2

let lenx, leny = Array.length x, Array.length y
Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in f x.[d] y.[r])
let lenx, leny = Array.length array1, Array.length array2
Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in mapping array1.[d] array2.[r])


/// <summary>Combines all values from three arrays and calls a mapping function on this combination.</summary>
/// <param name="mapping">Mapping function taking three element combination as input.</param>
/// <param name="list1">First array.</param>
/// <param name="list2">Second array.</param>
/// <param name="list3">Third array.</param>
/// <param name="array1">First array.</param>
/// <param name="array2">Second array.</param>
/// <param name="array3">Third array.</param>
///
/// <returns>Array with values returned from mapping function.</returns>
let lift3 mapping list1 list2 list3 =
raiseIfNull (nameof(list1)) list1
raiseIfNull (nameof(list2)) list2
raiseIfNull (nameof(list3)) list3
let lift3 (mapping: 'T1 -> 'T2 -> 'T3 -> 'U) (array1: 'T1 []) (array2: 'T2 []) (array3: 'T3 []) : 'U [] =
let array1 = nullArgCheck (nameof array1) array1
let array2 = nullArgCheck (nameof array2) array2
let array3 = nullArgCheck (nameof array3) array3

let lenx, leny, lenz = Array.length list1, Array.length list2, Array.length list3
let combinedFirstTwo = Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in (list1.[d], list2.[r]))
let lenx, leny, lenz = Array.length array1, Array.length array2, Array.length array3
let combinedFirstTwo = Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in (array1.[d], array2.[r]))

Array.init (lenx * leny * lenz) (fun i -> let (d, r) = Math.DivRem (i, lenz) in combinedFirstTwo.[d], list3.[r])
Array.init (lenx * leny * lenz) (fun i -> let (d, r) = Math.DivRem (i, lenz) in combinedFirstTwo.[d], array3.[r])
|> Array.map (fun x -> mapping (fst (fst x)) (snd (fst x)) (snd x))

/// Concatenates all elements, using the specified separator between each element.
let intercalate (separator: 'T []) (source: seq<'T []>) =
raiseIfNull (nameof(source)) source
let intercalate (separator: 'T []) (source: seq<'T []>) : 'T [] =
let separator = nullArgCheck (nameof separator) separator
let source = nullArgCheck (nameof source) source

#if FABLE_COMPILER
source |> Seq.intercalate separator |> Seq.toArray
Expand All @@ -88,8 +94,8 @@ module Array =
#endif

/// Inserts a separator element between each element in the source array.
let intersperse element (source: 'T []) =
raiseIfNull (nameof(source)) source
let intersperse element (source: 'T []) : 'T [] =
let source = nullArgCheck (nameof source) source

match source with
| [||] -> [||]
Expand All @@ -101,17 +107,17 @@ module Array =
| _ -> element)

/// Creates a sequence of arrays by splitting the source array on any of the given separators.
let split (separators: seq<_ []>) (source: _ []) =
raiseIfNull (nameof(separators)) separators
raiseIfNull (nameof(source)) source
let split (separators: seq<'T []>) (source: 'T []) : seq<'T []> =
let separators = nullArgCheck (nameof separators) separators
let source = nullArgCheck (nameof source) source

source |> Array.toSeq |> Seq.split separators |> Seq.map Seq.toArray

/// Replaces a subsequence of the source array with the given replacement array.
let replace (oldValue: 'T []) (newValue: 'T []) (source: 'T[]) : 'T[] =
raiseIfNull (nameof(oldValue)) oldValue
raiseIfNull (nameof(newValue)) newValue
raiseIfNull (nameof(source)) source
let oldValue = nullArgCheck (nameof oldValue) oldValue
let newValue = nullArgCheck (nameof newValue) newValue
let source = nullArgCheck (nameof source) source

#if FABLE_COMPILER
source |> Array.toSeq |> Seq.replace oldValue newValue |> Seq.toArray: 'T []
Expand Down Expand Up @@ -178,9 +184,9 @@ module Array =
/// <returns>
/// The index of the slice or <c>None</c>.
/// </returns>
let findSliceIndex (slice: _ []) (source: _ []) =
raiseIfNull (nameof(slice)) slice
raiseIfNull (nameof(source)) source
let findSliceIndex (slice: 'T []) (source: 'T []) : int =
let slice = nullArgCheck (nameof slice) slice
let source = nullArgCheck (nameof source) source

let index = Internals.FindSliceIndex.arrayImpl slice source
if index = -1 then
Expand All @@ -195,9 +201,9 @@ module Array =
/// <returns>
/// The index of the slice or <c>None</c>.
/// </returns>
let tryFindSliceIndex (slice: _ []) (source: _ []) =
raiseIfNull (nameof(slice)) slice
raiseIfNull (nameof(source)) source
let tryFindSliceIndex (slice: 'T []) (source: 'T []) : int option =
let slice = nullArgCheck (nameof slice) slice
let source = nullArgCheck (nameof source) source

let index = Internals.FindSliceIndex.arrayImpl slice source
if index = -1 then None else Some index
Expand All @@ -209,9 +215,9 @@ module Array =
/// <returns>
/// The index of the slice or <c>None</c>.
/// </returns>
let findLastSliceIndex (slice: _ []) (source: _ []) =
raiseIfNull (nameof(slice)) slice
raiseIfNull (nameof(source)) source
let findLastSliceIndex (slice: _ []) (source: _ []) : int =
let slice = nullArgCheck (nameof slice) slice
let source = nullArgCheck (nameof source) source

let index = Internals.FindLastSliceIndex.arrayImpl slice source
if index = -1 then
Expand All @@ -226,9 +232,9 @@ module Array =
/// <returns>
/// The index of the slice or <c>None</c>.
/// </returns>
let tryFindLastSliceIndex (slice: _ []) (source: _ []) =
raiseIfNull (nameof(slice)) slice
raiseIfNull (nameof(source)) source
let tryFindLastSliceIndex (slice: 'T []) (source: 'T []) : int option =
let slice = nullArgCheck (nameof slice) slice
let source = nullArgCheck (nameof source) source

let index = Internals.FindLastSliceIndex.arrayImpl slice source
if index = -1 then None else Some index
Expand All @@ -241,8 +247,8 @@ module Array =
/// <returns>
/// A tuple with both resulting arrays.
/// </returns>
let partitionMap (mapper: 'T -> Choice<'T1,'T2>) (source: array<'T>) =
raiseIfNull (nameof(source)) source
let partitionMap (mapper: 'T -> Choice<'T1, 'T2>) (source: array<'T>) : array<'T1> * array<'T2> =
let source = nullArgCheck (nameof source) source

let (x, y) = ResizeArray (), ResizeArray ()
Array.iter (mapper >> function Choice1Of2 e -> x.Add e | Choice2Of2 e -> y.Add e) source
Expand All @@ -251,19 +257,19 @@ module Array =
/// <summary>Safely build a new array whose elements are the results of applying the given function
/// to each of the elements of the two arrays pairwise.</summary>
/// <remark>If one array is shorter, excess elements are discarded from the right end of the longer array.</remark>
let map2Shortest f (a1: 'T []) (a2: 'U []) =
raiseIfNull (nameof(a1)) a1
raiseIfNull (nameof(a2)) a2
let map2Shortest (f: 'T1 -> 'T2 -> 'U) (a1: 'T1 []) (a2: 'T2 []) : 'U [] =
let a1 = nullArgCheck (nameof a1) a1
let a2 = nullArgCheck (nameof a2) a2

Array.init (min a1.Length a2.Length) (fun i -> f a1.[i] a2.[i])

/// <summary>Safely build a new array whose elements are the results of applying the given function
/// to each of the elements of the three arrays pairwise.</summary>
/// <remark>If one array is shorter, excess elements are discarded from the right end of the longer array.</remark>
let map3Shortest f (a1: 'T1 []) (a2: 'T2 []) (a3: 'T3 []) =
raiseIfNull (nameof a1) a1
raiseIfNull (nameof a2) a2
raiseIfNull (nameof a3) a3
let map3Shortest (f: 'T1 -> 'T2 -> 'T3 -> 'U) (a1: 'T1 []) (a2: 'T2 []) (a3: 'T3 []) : 'U [] =
let a1 = nullArgCheck (nameof a1) a1
let a2 = nullArgCheck (nameof a2) a2
let a3 = nullArgCheck (nameof a3) a3
Array.init (min a1.Length a2.Length |> min a3.Length) (fun i -> f a1.[i] a2.[i] a3.[i])

/// <summary>
Expand All @@ -272,9 +278,9 @@ module Array =
/// <param name="a1">First input array.</param>
/// <param name="a2">Second input array.</param>
/// <returns>Array with corresponding pairs of input arrays.</returns>
let zipShortest (a1: array<'T1>) (a2: array<'T2>) =
raiseIfNull (nameof(a1)) a1
raiseIfNull (nameof(a2)) a2
let zipShortest (a1: array<'T1>) (a2: array<'T2>) : array<'T1 * 'T2> =
let a1 = nullArgCheck (nameof a1) a1
let a2 = nullArgCheck (nameof a2) a2

Array.init (min a1.Length a2.Length) (fun i -> a1.[i], a2.[i])

Expand All @@ -285,19 +291,19 @@ module Array =
/// <param name="a2">Second input array.</param>
/// <param name="a3">Third input array.</param>
/// <returns>Array with corresponding tuple of input arrays.</returns>
let zip3Shortest (a1: array<'T1>) (a2: array<'T2>) (a3: array<'T3>) =
raiseIfNull (nameof a1) a1
raiseIfNull (nameof a2) a2
raiseIfNull (nameof a3) a3
let zip3Shortest (a1: array<'T1>) (a2: array<'T2>) (a3: array<'T3>) : array<'T1 * 'T2 * 'T3> =
let a1 = nullArgCheck (nameof a1) a1
let a2 = nullArgCheck (nameof a2) a2
let a3 = nullArgCheck (nameof a3) a3
Array.init (min a1.Length a2.Length |> min a3.Length) (fun i -> a1.[i], a2.[i], a3.[i])

/// <summary>Same as choose but with access to the index.</summary>
/// <param name="mapping">The mapping function, taking index and element as parameters.</param>
/// <param name="source">The input array.</param>
///
/// <returns>Array with values x for each Array value where the function returns Some(x).</returns>
let choosei mapping source =
raiseIfNull (nameof(source)) source
let choosei (mapping: int -> 'T -> 'U option) (source: array<'T>) : array<'U> =
let source = nullArgCheck (nameof source) source

let mutable i = ref -1
let fi x =
Expand Down
1 change: 1 addition & 0 deletions src/FSharpPlus/Extensions/Enumerator.fs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace FSharpPlus

#nowarn "3261" // nullness checks
#if !FABLE_COMPILER

/// Additional operations on IEnumerator
Expand Down
6 changes: 3 additions & 3 deletions src/FSharpPlus/Extensions/Exception.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ module Exception =

/// Throws the given exception with its original stacktrace.
let inline rethrow<'T> (exn: exn) =
raiseIfNull (nameof exn) exn
let exn = nullArgCheck (nameof exn) exn
(ExceptionDispatchInfo.Capture exn).Throw ()
Unchecked.defaultof<'T>

/// Combines exceptions from 2 exceptions into a single AggregateException.
/// Exceptions already present in the first argument won't be added.
let add (exn1: exn) (exn2: exn) =
raiseIfNull (nameof exn1) exn1
raiseIfNull (nameof exn2) exn2
let exn1 = nullArgCheck (nameof exn1) exn1
let exn2 = nullArgCheck (nameof exn2) exn2
let f (e: exn) =
match e with
:? AggregateException as a -> a.InnerExceptions :> seq<_>
Expand Down
7 changes: 4 additions & 3 deletions src/FSharpPlus/Extensions/Extensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace FSharpPlus
module Extensions =

open System
open FSharpPlus.Internals.Errors

type Collections.Generic.IEnumerable<'T> with
member this.GetSlice = function
Expand Down Expand Up @@ -39,7 +40,7 @@ module Extensions =

let private (|Canceled|Faulted|Completed|) (t: Task<'a>) =
if t.IsCanceled then Canceled
else if t.IsFaulted then Faulted t.Exception
else if t.IsFaulted then Faulted (Unchecked.nonNull t.Exception)
else Completed t.Result

type Task<'t> with
Expand Down Expand Up @@ -158,7 +159,7 @@ module Extensions =
Async.FromContinuations (fun (sc, ec, cc) ->
task.ContinueWith (fun (task: Task<'T>) ->
if task.IsFaulted then
let e = task.Exception
let e = Unchecked.nonNull task.Exception
if e.InnerExceptions.Count = 1 then ec e.InnerExceptions[0]
else ec e
elif task.IsCanceled then cc (TaskCanceledException ())
Expand All @@ -185,7 +186,7 @@ module Extensions =
Async.FromContinuations (fun (sc, ec, cc) ->
task.ContinueWith (fun (task: Task) ->
if task.IsFaulted then
let e = task.Exception
let e = Unchecked.nonNull task.Exception
if e.InnerExceptions.Count = 1 then ec e.InnerExceptions[0]
else ec e
elif task.IsCanceled then cc (TaskCanceledException ())
Expand Down
12 changes: 6 additions & 6 deletions src/FSharpPlus/Extensions/HashSet.fs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ module HashSet =
/// <returns>The union of <c>set1</c> and <c>set2</c>.</returns>
[<CompiledName("Union")>]
let union (source1: HashSet<'T>) (source2: HashSet<'T>) : HashSet<'T> =
raiseIfNull (nameof source1) source1
raiseIfNull (nameof source2) source2
let source1 = nullArgCheck (nameof source1) source1
let source2 = nullArgCheck (nameof source2) source2
let union =
#if FABLE_COMPILER
HashSet<'T> ()
Expand All @@ -50,7 +50,7 @@ module HashSet =
/// <returns>A set containing the transformed elements.</returns>
[<CompiledName("Map")>]
let map (mapping: 'T -> 'U) (source: HashSet<'T>) : HashSet<'U> =
raiseIfNull (nameof source) source
let source = nullArgCheck (nameof source) source
let result = empty<'U>
for item in source do
result.Add (mapping item) |> ignore
Expand All @@ -62,7 +62,7 @@ module HashSet =
/// <returns><c>true</c> if the set contains <c>value</c>; otherwise, <c>false</c>.</returns>
[<CompiledName("Contains")>]
let contains (value: 'T) (source: HashSet<'T>) : bool =
raiseIfNull (nameof source) source
let source = nullArgCheck (nameof source) source
source.Contains value

/// <summary>Determines whether the first set is a subset of the second set.</summary>
Expand All @@ -71,6 +71,6 @@ module HashSet =
/// <returns><c>true</c> if <c>source1</c> is a subset of <c>source2</c>; otherwise, <c>false</c>.</returns>
[<CompiledName("IsSubset")>]
let isSubset (source1: HashSet<'T>) (source2: HashSet<'T>) : bool =
raiseIfNull (nameof source1) source1
raiseIfNull (nameof source2) source2
let source1 = nullArgCheck (nameof source1) source1
let source2 = nullArgCheck (nameof source2) source2
source1.IsSubsetOf source2
5 changes: 3 additions & 2 deletions src/FSharpPlus/Extensions/List.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module List =

open System
open FSharp.Core.CompilerServices
open FSharpPlus.Internals.Errors

/// <summary>Returns a list that contains one item only.</summary>
///
Expand Down Expand Up @@ -475,7 +476,7 @@ module List =
open System.Reflection

/// Creates an infinite list which cycles the element of the source.
let cycle lst =
let cycle (lst: 'T list) =
let last = ref lst
let rec copy = function
| [] -> failwith "empty list"
Expand All @@ -486,7 +487,7 @@ module List =
| x::xs -> x::copy xs
let cycled = copy lst
let strs = last.Value.GetType().GetFields(BindingFlags.NonPublic ||| BindingFlags.Instance) |> Array.map (fun field -> field.Name)
let tailField = last.Value.GetType().GetField(Array.find(fun (s:string) -> s.ToLower().Contains("tail")) strs, BindingFlags.NonPublic ||| BindingFlags.Instance)
let tailField = last.Value.GetType().GetField(Array.find(fun (s:string) -> s.ToLower().Contains("tail")) strs, BindingFlags.NonPublic ||| BindingFlags.Instance) |> Unchecked.nonNull
tailField.SetValue(last.Value, cycled)
cycled
#else
Expand Down
Loading
Loading