简体   繁体   中英

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'])

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:

  • S.pipe does not feel natural to me in this case as there are two inputs ( source and ['foo', 'bar', 'baz'] ). Using S.pipe would necessitate hard-coding one of these inputs in the pipeline.

  • S.insert cannot be used for updating records, but S.unchecked.insert can be used for this purpose. I appreciate being able to suppress type checking when an expression I know to be sound is considered unsound by the type checker.

  • It's not clear to me from your question whether output order is important. Your solution respects the order of the array of section names; mine does not. Let me know whether output order is important.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM