0

I'm wondering if there is a more concise and efficient way to achieve the following code:

import { pipe } from 'fp-ts/function'
import * as A from 'fp-ts/Array'
import * as E from 'fp-ts/Option'

pipe(
  O.some(['foo', 'bar', 'baz']), // O.Option<string[]>
  O.map(A.map(mapFn)), // O.Option<Array<O.Option<string>>>
  O.chain(A.sequence(O.Applicative)), // O.Option<Array<string>>
)

Perhaps the root enclosing Option is detracting from the main point, but I'm basically trying to achieve the following transformation T[] -> Option<T[]> through mapping with mapFn which does T -> Option<T>.

I would be happy with this working example, although I can't help but notice that the A.map step completes entirely before the A.sequence step. If I could combine these two steps, then as soon as an element is mapped to O.None it would break (and not map the following elements unnecessarily).

james2mid
  • 35
  • 2
  • 5

1 Answers1

0

While writing this question, I discovered the traverseArray utility function which exists on Option and Either.

Now I'm able to perform the following and achieve the improved efficiency I mentioned at the end of the question. Whenever an element is mapped to a None, then traversal ends and passes a None to the next stage in the pipe.

pipe(
  O.some(['foo', 'bar', 'baz']), // O.Option<string[]>,
  O.chain(O.traverseArray(mapFn)), // O.Option<string[]>,
)
james2mid
  • 35
  • 2
  • 5
  • 1
    If you answered your own question, please mark it by accepting it as the official answer. – ImSo3K Nov 17 '21 at 11:15
  • Yes, `traverse` is `sequence` with mapping. Or, put another way, `sequence` is a specific usage of `traverse` with `identity` as the mapper – user1713450 Mar 17 '22 at 14:46