Fable: Manipulating maps returns odd results

Created on 19 Sep 2019  路  5Comments  路  Source: fable-compiler/Fable

Description

Manipulating some maps returns some odd results in Fable when compared with F#.
I personally think its because Fable may miscompile OptimizedClosures.FSharpFunc<_,_,_>.Adapt

Repro code

Link to repo

The test in question is described here.

The functions used in the test are implemented here

deepEqual is defined as Expecto.equalSequence when run with F# and as Assert.deepStrictEqual when run with JS.

Expected and actual results

In F# the test passes and the following gets printed:
m1: map [(1, "1"); (2, "2"); (3, "3")] m2: map [(3, "3"); (4, "4"); (5, "5")] r1: map [(3, "3")] r2: map [(3, "3")]

In Fable the test fails and the following gets printed:
m1: map [(1, 1); (2, 2); (3, 3)] m2: map [(3, 3); (4, 4); (5, 5)] r1: map [(3, a2 => f(a1, a2))] r2: map [(3, a2 => f(a1, a2))] map [(3, a2 => f(a1, a2))] map [(3, a2 => f(a1, a2))] 1) Map.intersect returns same results independent of the order (commutative)

Related information

  • Fable version: 2.3.25
  • Operating system: MacOS 10.14.6

Most helpful comment

Thank you both for the reports! Yes, the TODO comment here seems to indicate I wasn't very sure what I was doing when replacing that function 馃槄

Thanks to the JS diff kindly posted by @inosik I realized this was an issue with Fable uncurrying. With this commit your tests work now @jbotto94 :+1: (you can check here how to use Fable from source, but I will push a new fable-compiler release with the fix soon anyways).

All 5 comments

This change to Library/Library.fs makes it work:

 module Map =
     let mapValues2 f (x: Map<'Key, 'T1>) (y: Map<'Key, 'T2>) = Map <| seq {
-        let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f
         for KeyValue(k, vx) in x do
             match Map.tryFind k y with
-            | Some vy -> yield (k, f.Invoke (vx, vy))
+            | Some vy -> yield (k, f vx vy)
             | None    -> () }

Produces the following JS:

 import { ofSeq, tryFind } from "fable-library/Map";
 import { value } from "fable-library/Option";
 import { delay, collect, singleton, empty } from "fable-library/Seq";
-import { compare, curry } from "fable-library/Util";
+import { compare } from "fable-library/Util";
 export function mapValues2(f, x, y) {
   return ofSeq(delay(function () {
-    const f$$1 = f;
     return collect(function (matchValue) {
       const activePatternResult729 = matchValue;
       const matchValue$$1 = tryFind(activePatternResult729[0], y);

       if (matchValue$$1 == null) {
         return empty();
       } else {
         const vy = value(matchValue$$1);
-        return singleton([activePatternResult729[0], curry(2, f$$1)(activePatternResult729[1], vy)]);
+        return singleton([activePatternResult777[0], f(activePatternResult777[1], vy)]);
       }
     }, x);
   }), {
     Compare: compare
   });
 }

@inosik So that confirms that could be a bug in the way OptimizedClosures.FSharpFunc<_,_,_>.Adapt is compiled by Fable?

@jbotto94 Yes, it is a bug (or not implemented), I'll take a look. In the mean time, you can use System.Func<_,_,_>(f) instead.

Thank you both for the reports! Yes, the TODO comment here seems to indicate I wasn't very sure what I was doing when replacing that function 馃槄

Thanks to the JS diff kindly posted by @inosik I realized this was an issue with Fable uncurrying. With this commit your tests work now @jbotto94 :+1: (you can check here how to use Fable from source, but I will push a new fable-compiler release with the fix soon anyways).

@alfonsogarciacaro Thank you so much!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

stkb picture stkb  路  3Comments

funlambda picture funlambda  路  4Comments

SirUppyPancakes picture SirUppyPancakes  路  3Comments

alfonsogarciacaro picture alfonsogarciacaro  路  3Comments

nozzlegear picture nozzlegear  路  3Comments