javascriptfunctional-programmingsanctuary

A more idiomatic way to write sanctuary pipe


I wrote a code snippet that extracts the source object keys (which are supposed to be unknown so I've added a non-existing key baz to be extracted. Every element in the array that I extract - I want to add the key from which It was extracted and then flatten the result to get a single array.

I've encountered two major issues while writing the code:

  1. When trying to use S.insert, It always returned an error because the object values (numbers {r:**<<number>>**}) were of different type than the string i've tried to add to the key Section ({'Section': **'foo'**} for example). I ended up mutating the object just for the sake of conveying my intention.
  2. I didn't manage to write a proper map function that would abstract over the Maybe and let me access the variables inside. So I had to use S.maybeToNullable and then re-wrap the value into Maybe.
  3. Is there a better way of expressing any logic written below with sanctuary?

The code snippet:

const S = require('sanctuary');
const source = {
  foo: [{ r: 1 }, { r: 2 }, { r: 3 }],
  bar: [{ r: 4 }, { r: 5 }, { r: 6 }],
}

const result =
  S.pipe([
    S.map(
      prop => {
        const nullable = S.maybeToNullable(S.value(prop)(source))
        return nullable ? S.Just(nullable.map(val => {val['Section'] = prop; return val})) : S.Nothing
      }
    ),
    S.justs,
    S.reduce(xs => x => [...xs, ...x])([])
  ])(['foo', 'bar', 'baz'])

Solution

  • Here is my solution:

    const S = require ('sanctuary');
    
    //    source :: StrMap (Array { r :: Integer })
    const source = {
      foo: [{r: 1}, {r: 2}, {r: 3}],
      bar: [{r: 4}, {r: 5}, {r: 6}],
      quux: [{r: 7}, {r: 8}],
    };
    
    //    result :: Array { r :: Integer, Section :: String }
    const result =
    S.filter (S.compose (S.flip (S.elem) (['foo', 'bar', 'baz']))
                        (S.prop ('Section')))
             (S.chain (S.pair (s => S.map (S.unchecked.insert ('Section') (s))))
                      (S.pairs (source)));
    

    There are several things to note: