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: 2 additions & 0 deletions docsrc/content/abstraction-foldable.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ From .Net/F#
- ``seq<'T>``
- ``list<'T>``
- ``'T []``
- ``Set<'T>``
- ``HashSet<'T>``
- ``option<'T>``
- ``voption<'T>``
- ``ResizeArray<'T>``
Expand Down
1 change: 1 addition & 0 deletions docsrc/content/abstraction-functor.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ Restricted:
- ``string``
- ``StringBuilder``
- ``Set<'T>``
- ``HashSet<'T>``
- ``IEnumerator<'T>``
[Suggest another](https://github.com/fsprojects/FSharpPlus/issues/new) concrete implementation

Expand Down
1 change: 1 addition & 0 deletions docsrc/content/abstraction-monoid.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ From .Net/F#
- ``StringBuilder``
- ``unit``
- ``Set<'T>``
- ``HashSet<'T>``
- ``Map<'T,'Monoid>``
- ``TimeSpan``
- ``Tuple<'Monoid1* ... *'MonoidN>``
Expand Down
1 change: 1 addition & 0 deletions docsrc/content/abstraction-semigroup.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ From .Net/F#
- ``StringBuilder``
- ``unit``
- ``Set<'T>``
- ``HashSet<'T>``
- ``Map<'T, 'U>``
- ``TimeSpan``
- ``Tuple<*>``
Expand Down
1 change: 1 addition & 0 deletions src/FSharpPlus/Control/Functor.fs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ type Map =
static member Map ((x: StringBuilder , f ), _mthd: Map) = StringBuilder (String.map f (string x))
static member Map ((x: Set<_> , f ), _mthd: Map) = Set.map f x
static member Map ((_: Set2<'T> , _: 'T->'U), _mthd: Map) = Set2<'U>()
static member Map ((x: HashSet<_ > , f ), _mthd: Map) = HashSet.map f x


static member inline Invoke (mapping: 'T->'U) (source: '``Functor<'T>``) : '``Functor<'U>`` =
Expand Down
2 changes: 1 addition & 1 deletion src/FSharpPlus/Control/Monad.fs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ type Return =
static member Return (_: string , _: Return ) = fun (x: char) -> string x : string
static member Return (_: StringBuilder , _: Return ) = fun (x: char) -> new StringBuilder (string x) : StringBuilder
static member Return (_: 'a Set , _: Return ) = fun (x: 'a ) -> Set.singleton x
static member Return (_: 'a Set2 , _: Return ) = fun (_: 'a ) -> Set2() : 'a Set2
static member Return (_: 'a HashSet , _: Return ) = fun (x: 'a ) -> HashSet.singleton x


type Delay =
Expand Down
1 change: 1 addition & 0 deletions src/FSharpPlus/Control/Monoid.fs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Plus =
static member ``+`` (x: Set<_> , y , [<Optional>]_mthd: Plus ) = Set.union x y

#if !FABLE_COMPILER
static member ``+`` (x: HashSet<_> , y , [<Optional>]_mthd: Plus ) = HashSet.union x y
static member ``+`` (x: StringBuilder , y: StringBuilder , [<Optional>]_mthd: Plus ) = StringBuilder().Append(x).Append(y)
static member ``+`` (_: Id0 , _: Id0 , [<Optional>]_mthd: Plus ) = Id0 ""
static member ``+`` (x: AggregateException, y: AggregateException, [<Optional>]_mthd: Plus ) = Exception.add x y
Expand Down
4 changes: 3 additions & 1 deletion src/FSharpPlus/Control/Numeric.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace FSharpPlus.Control

open System.Runtime.InteropServices
open FSharpPlus.Internals
open FSharpPlus
#if FABLE_COMPILER
/// NOTE
type OptionalAttribute ()=
Expand Down Expand Up @@ -206,14 +207,15 @@ type Zero with
static member inline Zero (_: Lazy<'a> , _: Zero) = let (v: 'a) = Zero.Invoke () in lazy v
static member Zero (_: Dictionary<'a,'b> , _: Zero) = Dictionary<'a,'b> ()
static member Zero (_: ResizeArray<'a> , _: Zero) = ResizeArray () : ResizeArray<'a>
static member Zero (_: HashSet<'a> , _: Zero ) = HashSet.empty : HashSet<'a>

type Zero with
static member inline Zero (_: ^R , _: Default6) = FromInt64.Invoke 0L : ^R

static member inline Zero (_: ^R , _: Default5) = Implicit.Invoke 0 : ^R

static member Zero (_: seq<'a> , _: Default4) = Seq.empty : seq<'a>
static member Zero (_: IEnumerator<'a> , _: Default4) = FSharpPlus.Enumerator.Empty () : IEnumerator<'a>
static member Zero (_: IEnumerator<'a> , _: Default4) = Enumerator.Empty () : IEnumerator<'a>
static member Zero (_: IDictionary<'a,'b> , _: Default4) = Dictionary<'a,'b> () :> IDictionary<'a,'b>
static member Zero (_: IReadOnlyDictionary<'a,'b> , _: Default4) = Dictionary<'a,'b> () :> IReadOnlyDictionary<'a,'b>
static member inline Zero (_: 't , _: Default3) = (^t : (static member Empty: ^t) ()) : 't
Expand Down
4 changes: 2 additions & 2 deletions src/FSharpPlus/Control/ZipApplicative.fs
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ type Pure =
[<CompilerMessage(MessagePure + "ResizeArray<'t>.", Code, IsError = true)>]
static member Pure (x: ResizeArray<'a>, _: Pure ) = Return.Return (x, Unchecked.defaultof<Return>)

//Restricted
[<CompilerMessage(MessagePure + "string.", Code, IsError = true)>]
static member Pure (_: string , _: Pure ) = fun (x: char) -> string x : string
[<CompilerMessage(MessagePure + "StringBuilder.", Code, IsError = true)>]
static member Pure (_: StringBuilder , _: Pure ) = fun (x: char) -> new StringBuilder (string x) : StringBuilder
[<CompilerMessage(MessagePure + "Set.", Code, IsError = true)>]
static member Pure (_: 'a Set , _: Pure ) = fun (x: 'a ) -> Set.singleton x
static member Pure (_: 'a Set2 , _: Pure ) = fun (_: 'a ) -> Set2() : 'a Set2
[<CompilerMessage(MessagePure + "HashSet.", Code, IsError = true)>]
static member Pure (_: 'a HashSet , _: Pure ) = fun (x: 'a ) -> HashSet.singleton x

#endif

Expand Down
57 changes: 57 additions & 0 deletions src/FSharpPlus/Extensions/HashSet.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
namespace FSharpPlus

/// Additional operations on HashSet<'T>
[<RequireQualifiedAccess>]
module HashSet =
open System.Collections.Generic
open FSharpPlus.Internals.Errors

/// <summary>The empty set for the type 'T.</summary>
[<GeneralizableValue>]
[<CompiledName("Empty")>]
let empty<'T> : HashSet<'T> = HashSet<'T> ()

/// <summary>The set containing the given element.</summary>
/// <param name="value">The value for the set to contain.</param>
/// <returns>The set containing <c>value</c>.</returns>
[<CompiledName("Singleton")>]
let singleton (value: 'T) : HashSet<'T> =
let set =
#if FABLE_COMPILER
HashSet<'T> ()
#else
HashSet<'T> 1
#endif
set.Add value |> ignore
set

/// <summary>Computes the union of the two sets.</summary>
/// <param name="source1">The first input set.</param>
/// <param name="source2">The second input set.</param>
/// <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 union =
#if FABLE_COMPILER
HashSet<'T> ()
#else
HashSet<'T> (max source1.Count source2.Count)
#endif
for item in source1 do union.Add item |> ignore
for item in source2 do union.Add item |> ignore
union

/// <summary>Returns a new collection containing the results of applying the
/// given function to each element of the input set.</summary>
/// <param name="mapping">The function to transform elements of the input set.</param>
/// <param name="source">The input set.</param>
/// <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 result = empty<'U>
for item in source do
result.Add (mapping item) |> ignore
result
1 change: 1 addition & 0 deletions src/FSharpPlus/FSharpPlus.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<Compile Include="Extensions/Map.fs" />
<Compile Include="Extensions/Dictionary.fs" />
<Compile Include="Extensions/Dict.fs" />
<Compile Include="Extensions/HashSet.fs" />
<Compile Include="Extensions/IReadOnlyDictionary.fs" />
<Compile Include="Extensions/Enumerator.fs" />
<Compile Include="Extensions/Task.fs" />
Expand Down
8 changes: 8 additions & 0 deletions tests/FSharpPlus.Tests/Collections.fs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ module Collections =
let ls2:_ list = ofSeq (seq [(1, "One", '1'); (2, "Two", '2')])
let st1:_ Set = ofSeq {'1'..'3'}
let st2:_ Set = ofSeq (seq [(1, "One", '1'); (2, "Two", '2')])
let hs1:_ HashSet = ofSeq {'1'..'3'}
let hs2:_ HashSet = ofSeq (seq [(1, "One", '1'); (2, "Two", '2')])
let ss: Generic.SortedSet<_> = ofSeq (seq [3..6])
let ra: Generic.List<_> = ofSeq (seq [1..3])
let sl: Generic.SortedList<_,_> = ofSeq (seq [(1, "One"); (2, "Two")]) // but it will come back as ...
Expand Down Expand Up @@ -118,6 +120,8 @@ module Collections =
let _ls2' = toSeq ls2
let _st1' = toSeq st1
let _st2' = toSeq st2
let _hs1' = toSeq hs1
let _hs2' = toSeq hs2
let _ss' = toSeq ss
let _ra' = toSeq ra
let _sl' = toSeq sl
Expand Down Expand Up @@ -168,6 +172,8 @@ module Collections =
let ls2:_ list = ofList ([(1, "One", '1'); (2, "Two", '2')])
let st1:_ Set = ofList ['1'..'3']
let st2:_ Set = ofList ([(1, "One", '1'); (2, "Two", '2')])
let hs1:_ HashSet = ofList ['1'..'3']
let hs2:_ HashSet = ofList ([(1, "One", '1'); (2, "Two", '2')])
let ss: Generic.SortedSet<_> = ofList ([3..6])
let ra: Generic.List<_> = ofList ([1..3])
let sl: Generic.SortedList<_,_> = ofList ([(1, "One"); (2, "Two")]) // but it will come back as ...
Expand Down Expand Up @@ -218,6 +224,8 @@ module Collections =
let _ls2' = toList ls2
let _st1' = toList st1
let _st2' = toList st2
let _hs1' = toList hs1
let _hs2' = toList hs2
let _ss' = toList ss
let _ra' = toList ra
let _sl' = toList sl
Expand Down
19 changes: 19 additions & 0 deletions tests/FSharpPlus.Tests/Extensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,25 @@ module Extensions =

areEquivalent r1 r2

[<Test>]
let ``HashSet.union gives the same set when joined with an empty set (identity)`` () =
let m1 = HashSet.singleton "42"
let m2 = HashSet.empty

let r1 = HashSet.union m1 m2

areEquivalent r1 m1

[<Test>]
let ``HashSet.union returns same results independent of the order (commutative)`` () =
let m1 = HashSet [1..4]
let m2 = HashSet [3..6]

let r1 = HashSet.union m1 m2
let r2 = HashSet.union m2 m1

areEquivalent r1 r2

[<Test>]
let ``String.toCodePoints >> String.ofCodePoints should preserve the original string`` () =
// some naughty strings adopted from https://github.com/minimaxir/big-list-of-naughty-strings
Expand Down
Loading