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
22 changes: 8 additions & 14 deletions src/FSharpPlus/Control/Traversable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,14 @@ type Traverse =
#if TEST_TRACE
Traces.add "Traverse seq"
#endif
let cons x y = seq {yield x; yield! y}
let cons_f x ys = Map.Invoke (cons: 'a -> seq<_> -> seq<_>) (f x) <*> ys
let cons_f x ys = Map.Invoke (Seq.cons: 'a -> seq<_> -> seq<_>) (f x) <*> ys
Seq.foldBack cons_f t (result Seq.empty)

static member inline Traverse (t: _ NonEmptySeq, f, [<Optional>]_output: 'R, [<Optional>]_impl: Default3) =
#if TEST_TRACE
Traces.add "Traverse NonEmptySeq"
#endif
let cons x y = seq {yield x; yield! y}
let cons_f x ys = Map.Invoke (cons: 'a -> seq<_> -> seq<_>) (f x) <*> ys
let cons_f x ys = Map.Invoke (Seq.cons: 'a -> seq<_> -> seq<_>) (f x) <*> ys
Map.Invoke NonEmptySeq.ofSeq (Seq.foldBack cons_f t (result Seq.empty))

static member inline Traverse (t: seq<'T>, f: 'T -> '``Functor<'U>``, [<Optional>]_output: '``Functor<seq<'U>>``, [<Optional>]_impl: Default2) =
Expand Down Expand Up @@ -166,14 +164,13 @@ type Traverse =
#if TEST_TRACE
Traces.add "Traverse []"
#endif
let cons x y = Array.append [|x|] y
let rec loop acc = function
| [||] -> acc
| xxs ->
let x, xs = Array.head xxs, Array.tail xxs
let v = f x
loop (cons v acc) xs
let cons_f x xs = Map.Invoke cons xs <*> x
loop (Array.cons v acc) xs
let cons_f x xs = Map.Invoke Array.cons xs <*> x
Array.fold cons_f (result [||]) (loop [||] t)

static member inline Invoke (f: 'T -> '``Functor<'U>``) (t: '``Traversable<'T>``) : '``Functor<'Traversable<'U>>`` =
Expand All @@ -185,8 +182,7 @@ type Traverse =
type Sequence with

static member inline Sequence (t: _ seq, [<Optional>]_output: 'R, [<Optional>]_impl: Default5) : 'R =
let cons x y = seq { yield x; yield! y }
let cons_f x ys = Map.Invoke (cons: 'a -> seq<_> -> seq<_>) x <*> ys
let cons_f x ys = Map.Invoke (Seq.cons: 'a -> seq<_> -> seq<_>) x <*> ys
Seq.foldBack cons_f t (result Seq.empty)

static member inline Sequence (t: seq<'``Applicative<'T>``>, [<Optional>]_output: '``Applicative<seq<'T>>`` , [<Optional>]_impl: Default4) : '``Applicative<seq<'T>>`` =
Expand Down Expand Up @@ -409,14 +405,13 @@ type Gather =
#if TEST_TRACE
Traces.add "Gather []"
#endif
let cons x y = Array.append [|x|] y
let rec loop acc = function
| [||] -> acc
| xxs ->
let x, xs = Array.head xxs, Array.tail xxs
let v = f x
loop (cons v acc) xs
let cons_f x xs = Map.Invoke cons xs <.> x
loop (Array.cons v acc) xs
let cons_f x xs = Map.Invoke Array.cons xs <.> x
Array.fold cons_f (Pure.Invoke [||]) (loop [||] t)

static member inline Invoke (f: 'T -> '``Functor<'U>``) (t: '``Traversable<'T>``) : '``Functor<'Traversable<'U>>`` =
Expand All @@ -428,8 +423,7 @@ type Gather =
type Transpose with

static member inline Transpose (t: _ seq, [<Optional>]_output: 'R, [<Optional>]_impl: Default5) : 'R =
let cons x y = seq { yield x; yield! y }
let cons_f x ys = Map.Invoke (cons: 'a -> seq<_> -> seq<_>) x <.> ys
let cons_f x ys = Map.Invoke (Seq.cons: 'a -> seq<_> -> seq<_>) x <.> ys
Seq.foldBack cons_f t (Pure.Invoke Seq.empty)

static member inline Transpose (t: seq<'``Applicative<'T>``>, [<Optional>]_output: '``Applicative<seq<'T>>`` , [<Optional>]_impl: Default4) : '``Applicative<seq<'T>>`` =
Expand Down
28 changes: 24 additions & 4 deletions src/FSharpPlus/Data/NonEmptyList.fs
Original file line number Diff line number Diff line change
Expand Up @@ -148,19 +148,39 @@ module NonEmptyList =
let zipShortest (list1: NonEmptyList<'T>) (list2: NonEmptyList<'U>) =
{ Head = (list1.Head, list2.Head); Tail = List.zipShortest list1.Tail list2.Tail }

/// Returns a new NonEmptyList with the element added to the beginning.
let cons e {Head = x; Tail = xs} = {Head = e ; Tail = x::xs}
/// <summary>Adds an element to the beginning of the given list</summary>
/// <param name="value">The element to add</param>
/// <param name="list">The list to add to</param>
/// <returns>A new list with the element added to the beginning.</returns>
let cons e { Head = x; Tail = xs } = { Head = e ; Tail = x::xs }

/// <summary>Splits the list in head and tail.</summary>
/// <param name="list">The input list.</param>
/// <returns>A tuple with the head and the tail of the original list.</returns>
/// <exception cref="T:System.ArgumentException">Thrown when the input list tail is empty.</exception>
let uncons ({ Head = x; Tail = xs } as list) =
match xs with
| [] -> invalidArg (nameof(list)) "The input sequence has an empty tail"
| _ -> x, ofList xs

/// <summary>Splits the list in head and tail.</summary>
/// <param name="list">The input list.</param>
/// <returns>A tuple with the head and the tail of the original list.</returns>
let unconsAsList ({ Head = x; Tail = xs } as list) = x, xs

/// Returns the first element of a new non empty list. You can also use property nel.Head.
let head {Head = x; Tail = _ } = x

/// <summary>Returns a new NonEmptyList of the elements trailing the first element.</summary>
/// <exception cref="System.ArgumentException">Thrown when the tail is empty.</exception>
/// <remarks>Throws exception for empty tail</remarks>
let tail {Head = _; Tail = xs } = ofList xs
let tail ({ Head = _; Tail = xs } as list) =
match xs with
| [] -> invalidArg (nameof(list)) "The input sequence has an empty tail"
| _ -> ofList xs

/// <summary>Returns a new NonEmptyList of the elements trailing the first element or None.</summary>
let tryTail {Head = _; Tail = xs } = tryOfList xs
let tryTail { Head = _; Tail = xs } = tryOfList xs
let rec tails s =
let {Tail = xs} = s
match xs with
Expand Down
19 changes: 19 additions & 0 deletions src/FSharpPlus/Extensions/Array.fs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
namespace FSharpPlus

#nowarn "1204" // Suppress warning about using FSharp Compiler's error strings.

/// Additional operations on Array
[<RequireQualifiedAccess>]
module Array =
Expand All @@ -8,6 +10,23 @@ module Array =
open FSharp.Core.CompilerServices
open FSharpPlus.Internals.Errors

/// <summary>Adds an element to the beginning of the given array</summary>
/// <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
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
else array[0], array[1..]

/// <summary>Applies an array of functions to an array of values and concatenates them.</summary>
/// <param name="f">The array of functions.</param>
/// <param name="x">The array of values.</param>
Expand Down
16 changes: 13 additions & 3 deletions src/FSharpPlus/Extensions/List.fs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
namespace FSharpPlus

#nowarn "1204" // Suppress warning about using FSharp Compiler's error strings.

/// Additional operations on List
[<RequireQualifiedAccess>]
module List =
Expand Down Expand Up @@ -28,13 +30,21 @@ module List =
/// <summary>Adds an element to the beginning of the given list</summary>
/// <param name="value">The element to add</param>
/// <param name="list">The list to add to</param>
/// <returns>A concatenated list of the result lists of applying each function to each value</returns>
/// <returns>A new list with the element added to the beginning.</returns>
/// <remarks>
/// Note: this function has since been added to FSharp.Core.
/// It will be removed in next major release of FSharpPlus.
/// Same as <c>List.Cons</c> but with curried parameters.
/// </remarks>
let cons value list = value :: list : list<'T>

/// <summary>Splits the list in head and tail.</summary>
/// <param name="list">The input list.</param>
/// <returns>A tuple with the head and the tail of the original list.</returns>
/// <exception cref="T:System.ArgumentException">Thrown when the input list is empty.</exception>
let uncons list =
match list with
| [] -> invalidArg (nameof(list)) LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
| x::xs -> x, xs

/// <summary>Applies a list of functions to a list of values and concatenates them</summary>
/// <param name="f">The list of functions.</param>
/// <param name="x">The list of values.</param>
Expand Down
6 changes: 6 additions & 0 deletions src/FSharpPlus/Extensions/Seq.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ namespace FSharpPlus
module Seq =
open System

/// <summary>Adds an element to the beginning of the given sequence</summary>
/// <param name="value">The element to add</param>
/// <param name="source">The sequence to add to</param>
/// <returns>A new sequence with the element added to the beginning.</returns>
let cons value source = seq { yield value; yield! source } : seq<'T>

/// <summary>Applies the given function to each element of the sequence and concatenates the results.</summary>
///
/// <remarks>Remember sequence is lazy, effects are delayed until it is enumerated.</remarks>
Expand Down
2 changes: 1 addition & 1 deletion src/FSharpPlus/Lens.fs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ module Lens =
let foldlOf l f z = (flip Endo.run z << Dual.run) << foldMapOf l (Dual << Endo << flip f)

/// Extract a list of the targets of a Fold. See also (^..).
let toListOf l = let cons x y = x :: y in foldrOf l cons []
let toListOf l = foldrOf l List.cons []

/// Get the largest target of a Fold.
let maximumOf l =
Expand Down
Loading