Home > Mobile >  Is there a Do/Bind pattern to create an object containing different types in fp-ts?
Is there a Do/Bind pattern to create an object containing different types in fp-ts?

Time:11-25

I’m looking for something like Record.Do with Record.bind so I can do something like this

function getB: (a:A) => B
function getC: (b: B) => C
function getD: (c: C) => D

type Z = {
  a: A,
  b: B,
  c: C,
  d: D,
}

const getZ = (a: A): Z => pipe(
  R.Do,
  R.bind('a', () => a),
  R.bind('b', () => getB(a)),
  R.bind('c', (bindings) => getC(bindings.b)),
  R.bind('d', (bindings) => getD(bindings.c)),
)

I basically want to construct an object of different types while retaining all the inner objects of different types before applying some transformations on them

Not sure how to go about achieving this. I don’t want to take my types to other domains like Option, Either, IO; I feel like that just adds more code using O.some(s) or E.right(s) or IO.of(s) for transformations that don’t error.

This is the closes I could get

const getZ = (a: A): Z => pipe(
  IO.Do,
  IO.bind('a', () => () => a),
  IO.bind('b', () => () => getB(a)),
  IO.bind('c', (bindings) => () => getC(bindings.b)),
  IO.bind('d', (bindings) => () => getD(bindings.c)),
)()

CodePudding user response:

Why not just use the do notation on the Identity module? It's a type without any effects, so it should do what you want: https://gcanti.github.io/fp-ts/modules/Identity.ts.html#do-notation

CodePudding user response:

The imperative way to do this would be

const getZ = (a:A): Z => {
   const b = getB(a)
   const c = getC(b)
   const d = getD(c)
   return ({a, b, c, d})
}

More fp-ts, but still kinda imperative?

const getZ = (a: A): Z => pipe(
  a,
  (a) => ({ b: getB(a), a}),
  (bindings) => ({ c: getC(bindings.b), ...bindings })
  (bindings) => ({ d: getD(bindings.c), ...bindings })
)

Still looking for suggestions

  • Related