Skip to content

Commit 1f020f4

Browse files
committed
+ cons and uncons
1 parent 16ff2cb commit 1f020f4

File tree

4 files changed

+61
-5
lines changed

4 files changed

+61
-5
lines changed

src/FSharpPlus/Data/NonEmptyList.fs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,19 +148,39 @@ module NonEmptyList =
148148
let zipShortest (list1: NonEmptyList<'T>) (list2: NonEmptyList<'U>) =
149149
{ Head = (list1.Head, list2.Head); Tail = List.zipShortest list1.Tail list2.Tail }
150150

151-
/// Returns a new NonEmptyList with the element added to the beginning.
152-
let cons e {Head = x; Tail = xs} = {Head = e ; Tail = x::xs}
151+
/// <summary>Adds an element to the beginning of the given list</summary>
152+
/// <param name="value">The element to add</param>
153+
/// <param name="list">The list to add to</param>
154+
/// <returns>A new list with the element added to the beginning.</returns>
155+
let cons e { Head = x; Tail = xs } = { Head = e ; Tail = x::xs }
156+
157+
/// <summary>Splits the list in head and tail.</summary>
158+
/// <param name="list">The input list.</param>
159+
/// <returns>A tuple with the head and the tail of the original list.</returns>
160+
/// <exception cref="T:System.ArgumentException">Thrown when the input list tail is empty.</exception>
161+
let uncons ({ Head = x; Tail = xs } as list) =
162+
match xs with
163+
| [] -> invalidArg (nameof(list)) "The input sequence has an empty tail"
164+
| _ -> x, ofList xs
165+
166+
/// <summary>Splits the list in head and tail.</summary>
167+
/// <param name="list">The input list.</param>
168+
/// <returns>A tuple with the head and the tail of the original list.</returns>
169+
let unconsAsList ({ Head = x; Tail = xs } as list) = x, xs
153170

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

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

162182
/// <summary>Returns a new NonEmptyList of the elements trailing the first element or None.</summary>
163-
let tryTail {Head = _; Tail = xs } = tryOfList xs
183+
let tryTail { Head = _; Tail = xs } = tryOfList xs
164184
let rec tails s =
165185
let {Tail = xs} = s
166186
match xs with

src/FSharpPlus/Extensions/Array.fs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
namespace FSharpPlus
22

3+
#nowarn "1204" // Suppress warning about using FSharp Compiler's error strings.
4+
35
/// Additional operations on Array
46
[<RequireQualifiedAccess>]
57
module Array =
@@ -8,6 +10,23 @@ module Array =
810
open FSharp.Core.CompilerServices
911
open FSharpPlus.Internals.Errors
1012

13+
/// <summary>Adds an element to the beginning of the given array</summary>
14+
/// <param name="value">The element to add</param>
15+
/// <param name="array">The array to add to</param>
16+
/// <returns>A new array with the element added to the beginning.</returns>
17+
let cons value array =
18+
raiseIfNull (nameof(array)) array
19+
Array.insertAt 0 value array
20+
21+
/// <summary>Splits the array in head and tail.</summary>
22+
/// <param name="array">The input array.</param>
23+
/// <returns>A tuple with the head and the tail of the original array.</returns>
24+
/// <exception cref="T:System.ArgumentException">Thrown when the input array is empty.</exception>
25+
let uncons array =
26+
raiseIfNull (nameof(array)) array
27+
if Array.isEmpty array then invalidArg (nameof(array)) LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
28+
else array[0], array[1..]
29+
1130
/// <summary>Applies an array of functions to an array of values and concatenates them.</summary>
1231
/// <param name="f">The array of functions.</param>
1332
/// <param name="x">The array of values.</param>

src/FSharpPlus/Extensions/List.fs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
namespace FSharpPlus
22

3+
#nowarn "1204" // Suppress warning about using FSharp Compiler's error strings.
4+
35
/// Additional operations on List
46
[<RequireQualifiedAccess>]
57
module List =
@@ -28,12 +30,21 @@ module List =
2830
/// <summary>Adds an element to the beginning of the given list</summary>
2931
/// <param name="value">The element to add</param>
3032
/// <param name="list">The list to add to</param>
31-
/// <returns>A concatenated list of the result lists of applying each function to each value</returns>
33+
/// <returns>A new list with the element added to the beginning.</returns>
3234
/// <remarks>
3335
/// Same as <c>List.Cons</c> but with curried parameters.
3436
/// </remarks>
3537
let cons value list = value :: list : list<'T>
3638

39+
/// <summary>Splits the list in head and tail.</summary>
40+
/// <param name="list">The input list.</param>
41+
/// <returns>A tuple with the head and the tail of the original list.</returns>
42+
/// <exception cref="T:System.ArgumentException">Thrown when the input list is empty.</exception>
43+
let uncons list =
44+
match list with
45+
| [] -> invalidArg (nameof(list)) LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
46+
| x::xs -> x, xs
47+
3748
/// <summary>Applies a list of functions to a list of values and concatenates them</summary>
3849
/// <param name="f">The list of functions.</param>
3950
/// <param name="x">The list of values.</param>

src/FSharpPlus/Extensions/Seq.fs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ namespace FSharpPlus
55
module Seq =
66
open System
77

8+
/// <summary>Adds an element to the beginning of the given sequence</summary>
9+
/// <param name="value">The element to add</param>
10+
/// <param name="source">The sequence to add to</param>
11+
/// <returns>A new sequence with the element added to the beginning.</returns>
12+
let cons value source = seq { yield value; yield! source } : seq<'T>
13+
814
/// <summary>Applies the given function to each element of the sequence and concatenates the results.</summary>
915
///
1016
/// <remarks>Remember sequence is lazy, effects are delayed until it is enumerated.</remarks>

0 commit comments

Comments
 (0)