【问题标题】:Is using sequence the right approach to give monadic arguments to a function of arity greater than 1?使用序列为大于 1 的元数函数提供单子参数的正确方法吗?
【发布时间】:2018-04-03 18:25:38
【问题描述】:

见以下代码sn-p:

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 需要 3 个参数,我只想在它们都是 正确 参数的情况下提供它们。也就是说,sequence 将应用每个单子值,因此我会将它们作为单个 right 包含原始的 fun1fun2fun3 返回值。

这是推荐的方法吗?

Click here for run the whole code snippet

【问题讨论】:

    标签: javascript functional-programming monads ramda.js fantasyland


    【解决方案1】:

    不,我不会将sequence 与数组和apply 一起使用。我认为更惯用的方法是使用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);
    

    Haskell 中的等价物是fun5 =<< join (fun4 <$> fun1 <*> fun2 <*> fun3)unnestfun4 返回时需要 unnest,这可能不是必需的。

    【讨论】:

    • 嘿,Bergi。首先,感谢您的回答。 Haskell 中的等价物价格实惠,但 JavaScript 更难阅读,不是吗?当sequence 的噪音远低于此解决方案时,您会选择此解决方案吗?
    • 事实上,我什至可以包装 ramda 的 sequence 以使用 rest params 并且相同的调用看起来不那么嘈杂:sequence(Either.of, fun1(), fun2(), fun3())
    • @MatíasFidemraizer 是的,你可以做类似的事情,但是可变参数函数在类型系统中并不适用。最好叫它liftA3 like Haskell :-) 为了进一步提高可读性,请从“函数”中删除 Unit 参数,并将它们设为常量值。
    • 真的很难做出选择。最佳解决方案的可读性不如次优解决方案...我知道使用 apchain 可以避免不必要的迭代。
    • 再次感谢您的努力。事实上,第一种和第二种方法都是明确的方法,因为它们可以与任何应用程序一起使用,而第三种方法与 Either 相关联。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 2017-04-13
    • 2016-10-23
    • 2020-12-13
    • 1970-01-01
    • 2010-09-23
    • 2021-05-03
    相关资源
    最近更新 更多