Matías Fidemraizer
Matías Fidemraizer

Reputation: 64933

Is using sequence the right approach to give monadic arguments to a function of arity greater than 1?

See the following code snippet:

const
  fun1 = () => Either.of(1),
  fun2 = () => Either.of(2),
  fun3 = () => Either.of(3),
  fun4 = curry((x, y, z) => Either.of(x + y + z)),
  fun5 = x => Either.of(x + 1),
  fun6 = () => pipeK(
    () => sequence(Either.of, [fun1(), fun2(), fun3()]),
    apply(fun4),
    fun5
  )(),

result = fun6() // returns 7

fun4 requires 3 arguments and I'd like to give them only if all of them are right arguments. That is, sequence will apply each monadic value so I'll get them as a single right containg the raw fun1, fun2, fun3 return values.

Is this the recommended approach?

Click here for run the whole code snippet

Upvotes: 0

Views: 156

Answers (1)

Bergi
Bergi

Reputation: 664196

No, I would not use sequence with an array and apply. I think the more idiomatic approach is to use ap:

const fun6 = () => chain(fun5, unnest(ap(ap(ap(Either.of(fun4), fun1()), fun2()), fun3())));
// or
const fun6 = () => chain(fun5, unnest(ap(ap(map(fun4, fun1()), fun2()), fun3())));
// or
const fun6 = () => Either.of(fun4).ap(fun1()).ap(fun2()).ap(fun3()).chain(identity).chain(fun5);

The equivalent in Haskell would be fun5 =<< join (fun4 <$> fun1 <*> fun2 <*> fun3). The unnest is needed when fun4 returns an Either, which might not be necessary.

Upvotes: 2

Related Questions