Skip to content

Commit

Permalink
Fix bug in foldi for Map
Browse files Browse the repository at this point in the history
  • Loading branch information
gusty committed Feb 21, 2023
1 parent 54960d7 commit 7f93d61
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 48 deletions.
2 changes: 1 addition & 1 deletion src/FSharpPlus/Control/Indexable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ type FoldIndexed =
inherit Default1
static member FoldIndexed (x: list<_> , f, z, _impl: FoldIndexed) = x |> List.fold (fun (p, i) t -> (f p i t, i + 1)) (z, 0) |> fst
static member FoldIndexed (x: _ [] , f, z, _impl: FoldIndexed) = x |> Array.fold (fun (p, i) t -> (f p i t, i + 1)) (z, 0) |> fst
static member FoldIndexed (_: Map<'k,'t>, f, z, _impl: FoldIndexed) = Map.fold f z
static member FoldIndexed (x: Map<'k,'t>, f, z, _impl: FoldIndexed) = Map.fold f z x

static member inline Invoke (folder: 'State->'Key->'T->'State) (state: 'State) (foldable: '``Foldable<'T>``) : 'State =
let inline call_2 (a: ^a, b: ^b, f, z) = ((^a or ^b) : (static member FoldIndexed : _*_*_*_ -> _) b, f, z, a)
Expand Down
1 change: 1 addition & 0 deletions tests/FSharpPlus.Tests/FSharpPlus.Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<Compile Include="Monoid.fs" />
<Compile Include="Parsing.fs" />
<Compile Include="Traversals.fs" />
<Compile Include="Indexables.fs" />
<Compile Include="Validations.fs" />
<Compile Include="Task.fs" />
<Compile Include="ValueTask.fs" />
Expand Down
42 changes: 0 additions & 42 deletions tests/FSharpPlus.Tests/General.fs
Original file line number Diff line number Diff line change
Expand Up @@ -915,48 +915,6 @@ module Foldable =
areEqual sb' None
()

module Indexable =
[<Test>]
let testCompileAndExecuteItem () =

let a = Map.ofSeq [1, "one"; 2, "two"]
let _ = item 1 a

let b = dict [1, "one"; 2, "two"]
let _ = item 1 b

let c = "two"
let _ = item 1 c

let d = System.Text.StringBuilder "one"
let _ = item 1 d

let e = array2D [[1;2];[3;4];[5;6]]
let _ = item (1, 1) e

let f = [1, "one"; 2, "two"]
let _ = item 1 f

let g = [|1, "one"; 2, "two"|]
let _ = item 1 g

let h = ResizeArray [1, "one"; 2, "two"]
let _ = item 1 h

let i = Array3D.create 3 2 2 0
let _ = item (1, 1, 1) i

let j = Array4D.create 3 2 2 3 0
let _ = item (1, 1, 1, 1) j

let k = NonEmptyMap.Create (("a", 1), ("b", 2))
let _ = item "b" k

// This doesn't intentionally compile: seq is not Indexable. Not all foldables are Indexable, for example a Set is foldable but not Indexable. For seq use nth instead.
// let f = seq [1, "one"; 2, "two"]
// let _ = item 1 f

()

[<Test>]
let testCompileAndExecuteTryItem () =
Expand Down
79 changes: 79 additions & 0 deletions tests/FSharpPlus.Tests/Indexables.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
namespace FSharpPlus.Tests

#nowarn "686"

open System
open System.Collections.Generic
open FSharpPlus
open FSharpPlus.Data
open FSharpPlus.Control
open NUnit.Framework
open Helpers


module Indexables =

[<Test>]
let testCompileAndExecuteItem () =

let a = Map.ofSeq [1, "one"; 2, "two"]
let _ = item 1 a

let b = dict [1, "one"; 2, "two"]
let _ = item 1 b

let c = "two"
let _ = item 1 c

let d = System.Text.StringBuilder "one"
let _ = item 1 d

let e = array2D [[1;2];[3;4];[5;6]]
let _ = item (1, 1) e

let f = [1, "one"; 2, "two"]
let _ = item 1 f

let g = [|1, "one"; 2, "two"|]
let _ = item 1 g

let h = ResizeArray [1, "one"; 2, "two"]
let _ = item 1 h

let i = Array3D.create 3 2 2 0
let _ = item (1, 1, 1) i

let j = Array4D.create 3 2 2 3 0
let _ = item (1, 1, 1, 1) j

let k = NonEmptyMap.Create (("a", 1), ("b", 2))
let _ = item "b" k

// This doesn't intentionally compile: seq is not Indexable. Not all foldables are Indexable, for example a Set is foldable but not Indexable. For seq use nth instead.
// let f = seq [1, "one"; 2, "two"]
// let _ = item 1 f

()

[<Test>]
let foldIndexed () =
Assert.AreEqual (123, foldi (fun a b c -> a + b + c) 0 (seq [20; 40; 60]))
Assert.AreEqual (123, foldi (fun a b c -> a + b + c) 0 [20; 40; 60])


[<Test>]
let traverseIndexed () =
let m1 = Map.ofList [(1, [1;1;1]); (2, [2;2;2])]
let r1 = m1 |> traversei (fun _ _ -> None)
let r2 = m1 |> traversei (fun i v -> if List.forall ((=) i) v then Some (i :: v) else None)
AreEqual (None = r1)
CollectionAssert.AreEqual (Map.ofList [(1, [1;1;1;1]); (2, [2;2;2;2])], r2.Value)
Assert.IsInstanceOf<Option<Map<int,int list>>> (Some r2.Value)

let r3 = seq [ ( [0;0;0]); ( [1;1;1]); ( [2;2;2])] |> traversei (fun i v -> if List.forall ((=) i) v then Some (i :: v) else None)
CollectionAssert.AreEqual (seq [[0; 0; 0]; [1; 1; 1]; [2; 2; 2]], r3.Value)
Assert.IsInstanceOf<Option<seq<int list>>> (Some r3.Value)

let r4 = [ ( [0;0;0]); ( [1;1;1]); ( [2;2;2])] |> traversei (fun i v -> if List.forall ((=) i) v then Some (i :: v) else None)
CollectionAssert.AreEqual ([[0; 0; 0; 0]; [1; 1; 1; 1]; [2; 2; 2; 2]], r4.Value)
Assert.IsInstanceOf<Option<int list list>> (Some r4.Value)
5 changes: 0 additions & 5 deletions tests/FSharpPlus.Tests/Traversals.fs
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,6 @@ module Traversable =
CollectionAssert.AreEqual (r2.Value, m)

let m1 = Map.ofList [(1, [1;1;1]); (2, [2;2;2])]
let r1 = m1 |> traversei (fun _ _ -> None)
let r2 = m1 |> traversei (fun i v -> if List.forall ((=) i) v then Some (i :: v) else None)
Assert.AreEqual(None, r1)
CollectionAssert.AreEqual (Map.ofList [(1, [1;1;1;1]); (2, [2;2;2;2])], r2.Value)

let expected = [Map.ofList [(1, 1); (2, 2)]; Map.ofList [(1, 1); (2, 2)]; Map.ofList [(1, 1); (2, 2)];
Map.ofList [(1, 1); (2, 2)]; Map.ofList [(1, 1); (2, 2)]; Map.ofList [(1, 1); (2, 2)];
Map.ofList [(1, 1); (2, 2)]; Map.ofList [(1, 1); (2, 2)]; Map.ofList [(1, 1); (2, 2)]]
Expand Down

0 comments on commit 7f93d61

Please sign in to comment.