diff --git a/src/FSharpPlus/Control/Monad.fs b/src/FSharpPlus/Control/Monad.fs index 2260364ec..89172e518 100644 --- a/src/FSharpPlus/Control/Monad.fs +++ b/src/FSharpPlus/Control/Monad.fs @@ -50,13 +50,29 @@ type Bind = | Some v -> yield k, v | _ -> () }) - static member (>>=) (source: Dictionary<'Key,'T>, f: 'T -> Dictionary<'Key,'U>) = - let dct = Dictionary () - for KeyValue(k, v) in source do - match (f v).TryGetValue (k) with - | true, v -> dct.Add (k, v) - | _ -> () - dct + static member (>>=) (source: Dictionary<'Key,'T>, f: 'T -> Dictionary<'Key,'U>) = + let dct = Dictionary () + for KeyValue(k, v) in source do + match (f v).TryGetValue (k) with + | true, v -> dct.Add (k, v) + | _ -> () + dct + + static member (>>=) (source: IDictionary<'Key,'T>, f: 'T -> IDictionary<'Key,'U>) = + let dct = Dictionary () + for KeyValue(k, v) in source do + match (f v).TryGetValue (k) with + | true, v -> dct.Add (k, v) + | _ -> () + dct :> IDictionary<'Key,'U> + + static member (>>=) (source: IReadOnlyDictionary<'Key,'T>, f: 'T -> IReadOnlyDictionary<'Key,'U>) = + let dct = Dictionary () + for KeyValue(k, v) in source do + match (f v).TryGetValue (k) with + | true, v -> dct.Add (k, v) + | _ -> () + dct :> IReadOnlyDictionary<'Key,'U> static member (>>=) (source: ResizeArray<'T>, f: 'T -> ResizeArray<'U>) = ResizeArray (Seq.bind (f >> seq<_>) source) : ResizeArray<'U> @@ -114,6 +130,22 @@ type Join = | _ -> () dct + static member Join (x: IDictionary<_, IDictionary<_, _>>, []_output: IDictionary<'Key, 'Value>, []_mthd: Join) : IDictionary<'Key, 'Value> = + let dct = Dictionary () + for KeyValue(k, v) in x do + match v.TryGetValue (k) with + | true, v -> dct.Add (k, v) + | _ -> () + dct :> IDictionary<'Key, 'U> + + static member Join (x: IReadOnlyDictionary<_, IReadOnlyDictionary<_, _>>, []_output: IReadOnlyDictionary<'Key, 'Value>, []_mthd: Join) : IReadOnlyDictionary<'Key, 'Value> = + let dct = Dictionary () + for KeyValue(k, v) in x do + match v.TryGetValue (k) with + | true, v -> dct.Add (k, v) + | _ -> () + dct :> IReadOnlyDictionary<'Key, 'U> + static member Join (x: ResizeArray> , []_output: ResizeArray<'T> , []_mthd: Join) = ResizeArray (Seq.bind seq<_> x) : ResizeArray<'T> static member Join (x: NonEmptySeq> , []_output: NonEmptySeq<'T> , []_mthd: Join) = NonEmptySeq.concat x : NonEmptySeq<'T> diff --git a/tests/FSharpPlus.Tests/FSharpPlus.Tests.fsproj b/tests/FSharpPlus.Tests/FSharpPlus.Tests.fsproj index 734bf6e45..b9dfcf836 100644 --- a/tests/FSharpPlus.Tests/FSharpPlus.Tests.fsproj +++ b/tests/FSharpPlus.Tests/FSharpPlus.Tests.fsproj @@ -19,6 +19,7 @@ + diff --git a/tests/FSharpPlus.Tests/General.fs b/tests/FSharpPlus.Tests/General.fs index 97d0d522c..62da5a027 100644 --- a/tests/FSharpPlus.Tests/General.fs +++ b/tests/FSharpPlus.Tests/General.fs @@ -1089,30 +1089,6 @@ module IdiomBrackets = let res3n4''' = iI (+) (result 2) [1;2] Ii // fails to compile when constraints are not properly defined Assert.AreEqual ([3;4], res3n4'' ) Assert.AreEqual ([3;4], res3n4''') - - - let output = System.Text.StringBuilder () - let append (x: string) = output.Append x |> ignore - - let v5: Lazy<_> = lazy (append "5"; 5) - Assert.AreEqual (0, output.Length) - let fPlus10 x = lazy (append " + 10"; x + 10) - Assert.AreEqual (0, output.Length) - let v5plus10 = v5 >>= fPlus10 - Assert.AreEqual (0, output.Length) - let v15 = v5plus10.Force () - Assert.AreEqual ("5 + 10", string output) - Assert.AreEqual (15, v15) - - output.Clear () |> ignore - - let v4ll: Lazy<_> = lazy (append "outer"; lazy (append "inner"; 4)) - Assert.AreEqual (0, output.Length) - let v4l = join v4ll - Assert.AreEqual (0, output.Length) - let v4 = v4l.Force() - Assert.AreEqual ("outerinner", string output) - Assert.AreEqual (4, v4) module Alternative = diff --git a/tests/FSharpPlus.Tests/Monads.fs b/tests/FSharpPlus.Tests/Monads.fs new file mode 100644 index 000000000..23c0e9901 --- /dev/null +++ b/tests/FSharpPlus.Tests/Monads.fs @@ -0,0 +1,43 @@ +namespace FSharpPlus.Tests + +open System +open System.Collections.ObjectModel +open FSharpPlus +open FSharpPlus.Data +open NUnit.Framework +open Helpers + +module Monads = + + [] + let lazies () = + let output = System.Text.StringBuilder () + let append (x: string) = output.Append x |> ignore + + let v5: Lazy<_> = lazy (append "5"; 5) + Assert.AreEqual (0, output.Length) + let fPlus10 x = lazy (append " + 10"; x + 10) + Assert.AreEqual (0, output.Length) + let v5plus10 = v5 >>= fPlus10 + Assert.AreEqual (0, output.Length) + let v15 = v5plus10.Force () + Assert.AreEqual ("5 + 10", string output) + Assert.AreEqual (15, v15) + + output.Clear () |> ignore + + let v4ll: Lazy<_> = lazy (append "outer"; lazy (append "inner"; 4)) + Assert.AreEqual (0, output.Length) + let v4l = join v4ll + Assert.AreEqual (0, output.Length) + let v4 = v4l.Force() + Assert.AreEqual ("outerinner", string output) + Assert.AreEqual (4, v4) + + [] + let mapLikes () = + let r1 = dict [ "a", 1; "b", 2 ; "c", 3 ] >>= fun x -> dict [ "a", x + 10; "c", x + 300; "d", x + 400 ] + CollectionAssert.AreEqual (dict [ "a", 11; "c", 303 ], r1) + + let r2 = readOnlyDict [ "a", 1; "b", 2 ; "c", 3 ] >>= fun x -> readOnlyDict [ "a", x + 10; "c", x + 300; "d", x + 400 ] + CollectionAssert.AreEqual (readOnlyDict [ "a", 11; "c", 303 ], r2)